diff --git a/.make/composer/rmDeniedTestDir.php b/.make/composer/rmDeniedTestDir.php index 6a5f7837c..a7f0072c5 100644 --- a/.make/composer/rmDeniedTestDir.php +++ b/.make/composer/rmDeniedTestDir.php @@ -50,14 +50,24 @@ foreach ($aDeniedButStillPresent as $sDir) continue; } - try - { + try { SetupUtils::rrmdir($sDir); echo "OK Remove denied test dir: '$sDir'\n"; } - catch (\Exception $e) - { + catch (\Exception $e) { echo "\nFAILED to remove denied test dir: '$sDir'\n"; } +} + +$aAllowedAndDeniedDirs = array_merge( + $oiTopComposer->ListAllowedTestDir(), + $oiTopComposer->ListDeniedTestDir() +); +$aExistingDirs = $oiTopComposer->ListAllTestDir(); +$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs); +if (false === empty($aMissing)) { + echo "Some new tests dirs exists !\n" + .' They must be declared either in the allowed or denied list in '.iTopComposer::class." (see N°2651).\n" + .' List of dirs:'."\n".var_export($aMissing, true); } \ No newline at end of file diff --git a/composer.json b/composer.json index 5806de5fa..9ceb05ac3 100644 --- a/composer.json +++ b/composer.json @@ -10,18 +10,18 @@ "ext-json": "*", "ext-mysqli": "*", "ext-soap": "*", - "combodo/tcpdf": "6.3.5", - "nikic/php-parser": "^4.12.0", - "pear/archive_tar": "1.4.14", - "pelago/emogrifier": "3.1.0", - "scssphp/scssphp": "1.0.6", - "swiftmailer/swiftmailer": "5.4.12", + "combodo/tcpdf": "~6.4.4", + "nikic/php-parser": "~4.13.2", + "pear/archive_tar": "~1.4.14", + "pelago/emogrifier": "~3.1.0", + "scssphp/scssphp": "~1.10.2", + "swiftmailer/swiftmailer": "~6.3.0", "symfony/console": "~3.4.47", "symfony/dotenv": "~3.4.47", "symfony/framework-bundle": "~3.4.47", - "symfony/polyfill-php70": "1.*", "symfony/twig-bundle": "~3.4.47", - "symfony/yaml": "~3.4.47" + "symfony/yaml": "~3.4.47", + "twig/twig": "~1.42.5" }, "require-dev": { "symfony/stopwatch": "~3.4.47", diff --git a/composer.lock b/composer.lock index 63a0c2e1c..580575a0f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4c5cdd1e0feb4abaab8f86959ffc7a64", + "content-hash": "4be638854dcbc0af5f63f9d2fd079d33", "packages": [ { "name": "combodo/tcpdf", - "version": "6.3.5", + "version": "6.4.4", "source": { "type": "git", "url": "https://github.com/combodo-itop-libs/TCPDF.git", - "reference": "aedd4b7b8cf7fcc24e617c405c9d3304150f4b94" + "reference": "0e31c013ccd000aa6762e9186778aa6e259ac8e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/combodo-itop-libs/TCPDF/zipball/aedd4b7b8cf7fcc24e617c405c9d3304150f4b94", - "reference": "aedd4b7b8cf7fcc24e617c405c9d3304150f4b94", + "url": "https://api.github.com/repos/combodo-itop-libs/TCPDF/zipball/0e31c013ccd000aa6762e9186778aa6e259ac8e8", + "reference": "0e31c013ccd000aa6762e9186778aa6e259ac8e8", "shasum": "" }, "require": { @@ -62,22 +62,184 @@ "email": "contact@combodo.com" } ], - "description": "TCPDF fork adding requirements for iTop: Specific fonts.", + "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", "homepage": "https://github.com/combodo-itop-libs/TCPDF", - "time": "2020-09-28T12:19:09+00:00" + "keywords": [ + "PDFD32000-2008", + "TCPDF", + "barcodes", + "datamatrix", + "pdf", + "pdf417", + "qrcode" + ], + "support": { + "source": "https://github.com/combodo-itop-libs/TCPDF/tree/6.4.4" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20tcpdf%20project", + "type": "custom" + } + ], + "time": "2022-03-10T14:36:39+00:00" }, { - "name": "nikic/php-parser", - "version": "v4.12.0", + "name": "doctrine/lexer", + "version": "1.2.3", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "6608f01670c3cc5079e18c1dab1104e002579143" + "url": "https://github.com/doctrine/lexer.git", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6608f01670c3cc5079e18c1dab1104e002579143", - "reference": "6608f01670c3cc5079e18c1dab1104e002579143", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.3" + }, + "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%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-02-28T11:07:21+00:00" + }, + { + "name": "egulias/email-validator", + "version": "2.1.25", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/0dbf5d78455d4d6a41d186da50adc1122ec066f4", + "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1.0.1", + "php": ">=5.5", + "symfony/polyfill-intl-idn": "^1.10" + }, + "require-dev": { + "dominicsayers/isemail": "^3.0.7", + "phpunit/phpunit": "^4.8.36|^7.5.15", + "satooshi/php-coveralls": "^1.0.1" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/2.1.25" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2020-12-29T14:50:06+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.13.2", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077", "shasum": "" }, "require": { @@ -118,9 +280,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.12.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" }, - "time": "2021-07-21T10:44:31+00:00" + "time": "2021-11-30T19:35:32+00:00" }, { "name": "paragonie/random_compat", @@ -679,16 +841,16 @@ }, { "name": "scssphp/scssphp", - "version": "1.0.6", + "version": "v1.10.2", "source": { "type": "git", "url": "https://github.com/scssphp/scssphp.git", - "reference": "5b3c9d704950d8f9637f5110c36c281ec47dc13c" + "reference": "387f4f4abf5d99f16be16314c5ab856f81c82f46" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/scssphp/scssphp/zipball/5b3c9d704950d8f9637f5110c36c281ec47dc13c", - "reference": "5b3c9d704950d8f9637f5110c36c281ec47dc13c", + "url": "https://api.github.com/repos/scssphp/scssphp/zipball/387f4f4abf5d99f16be16314c5ab856f81c82f46", + "reference": "387f4f4abf5d99f16be16314c5ab856f81c82f46", "shasum": "" }, "require": { @@ -697,11 +859,20 @@ "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3", - "squizlabs/php_codesniffer": "~2.5", - "twbs/bootstrap": "~4.3", + "bamarni/composer-bin-plugin": "^1.4", + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4", + "sass/sass-spec": "*", + "squizlabs/php_codesniffer": "~3.5", + "symfony/phpunit-bridge": "^5.1", + "thoughtbot/bourbon": "^7.0", + "twbs/bootstrap": "~5.0", + "twbs/bootstrap4": "4.6.1", "zurb/foundation": "~6.5" }, + "suggest": { + "ext-iconv": "Can be used as fallback when ext-mbstring is not available", + "ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv" + }, "bin": [ "bin/pscss" ], @@ -736,33 +907,44 @@ "scss", "stylesheet" ], - "time": "2019-12-12T05:00:52+00:00" + "support": { + "issues": "https://github.com/scssphp/scssphp/issues", + "source": "https://github.com/scssphp/scssphp/tree/v1.10.2" + }, + "time": "2022-03-02T21:15:09+00:00" }, { "name": "swiftmailer/swiftmailer", - "version": "v5.4.12", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "181b89f18a90f8925ef805f950d47a7190e9b950" + "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950", - "reference": "181b89f18a90f8925ef805f950d47a7190e9b950", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/8a5d5072dca8f48460fce2f4131fcc495eec654c", + "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c", "shasum": "" }, "require": { - "php": ">=5.3.3" + "egulias/email-validator": "^2.0|^3.1", + "php": ">=7.0.0", + "symfony/polyfill-iconv": "^1.0", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" }, "require-dev": { - "mockery/mockery": "~0.9.1", - "symfony/phpunit-bridge": "~3.2" + "mockery/mockery": "^1.0", + "symfony/phpunit-bridge": "^4.4|^5.4" + }, + "suggest": { + "ext-intl": "Needed to support internationalized email addresses" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.4-dev" + "dev-master": "6.2-dev" } }, "autoload": { @@ -790,7 +972,22 @@ "mail", "mailer" ], - "time": "2018-07-31T09:26:32+00:00" + "support": { + "issues": "https://github.com/swiftmailer/swiftmailer/issues", + "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.3.0" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/swiftmailer/swiftmailer", + "type": "tidelift" + } + ], + "abandoned": "symfony/mailer", + "time": "2021-10-18T15:26:12+00:00" }, { "name": "symfony/cache", @@ -2037,6 +2234,260 @@ ], "time": "2020-10-23T09:01:57+00:00" }, + { + "name": "symfony/polyfill-iconv", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-iconv.git", + "reference": "f1aed619e28cb077fc83fac8c4c0383578356e40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/f1aed619e28cb077fc83fac8c4c0383578356e40", + "reference": "f1aed619e28cb077fc83fac8c4c0383578356e40", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-iconv": "*" + }, + "suggest": { + "ext-iconv": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Iconv\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Iconv extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "iconv", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-04T09:04:05+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "749045c69efb97c70d25d7463abba812e91f3a44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/749045c69efb97c70d25d7463abba812e91f3a44", + "reference": "749045c69efb97c70d25d7463abba812e91f3a44", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-intl-normalizer": "^1.10", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-09-14T14:02:44+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-19T12:13:01+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.19.0", @@ -2274,6 +2725,82 @@ ], "time": "2020-10-23T09:01:57+00:00" }, + { + "name": "symfony/polyfill-php72", + "version": "v1.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-27T09:17:38+00:00" + }, { "name": "symfony/polyfill-util", "version": "v1.19.0", @@ -2698,16 +3225,16 @@ }, { "name": "twig/twig", - "version": "v1.42.4", + "version": "v1.42.5", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "e587180584c3d2d6cb864a0454e777bb6dcb6152" + "reference": "87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/e587180584c3d2d6cb864a0454e777bb6dcb6152", - "reference": "e587180584c3d2d6cb864a0454e777bb6dcb6152", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e", + "reference": "87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e", "shasum": "" }, "require": { @@ -2716,8 +3243,7 @@ }, "require-dev": { "psr/container": "^1.0", - "symfony/debug": "^3.4|^4.2", - "symfony/phpunit-bridge": "^4.4@dev|^5.0" + "symfony/phpunit-bridge": "^4.4|^5.0" }, "type": "library", "extra": { @@ -2746,7 +3272,6 @@ }, { "name": "Twig Team", - "homepage": "https://twig.symfony.com/contributors", "role": "Contributors" }, { @@ -2760,7 +3285,11 @@ "keywords": [ "templating" ], - "time": "2019-11-11T16:49:32+00:00" + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/1.x" + }, + "time": "2020-02-11T05:59:23+00:00" } ], "packages-dev": [ @@ -3007,5 +3536,5 @@ "platform-overrides": { "php": "7.1.3" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.3.0" } diff --git a/core/email.class.inc.php b/core/email.class.inc.php index 1470befaf..193d1e53e 100644 --- a/core/email.class.inc.php +++ b/core/email.class.inc.php @@ -510,23 +510,17 @@ class EMail class Swift_Transport_LogFileTransport extends Swift_Transport_NullTransport { protected $sLogFile; - + /** - * Sends the given message. - * - * @param Swift_Mime_Message $message - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent emails + * @inheritDoc */ - public function send(Swift_Mime_Message $message, &$failedRecipients = null) + public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null) { $hFile = @fopen($this->sLogFile, 'a'); - if ($hFile) - { + if ($hFile) { $sTxt = "================== ".date('Y-m-d H:i:s')." ==================\n"; $sTxt .= $message->toString()."\n"; - + @fwrite($hFile, $sTxt); @fclose($hFile); } @@ -551,12 +545,13 @@ class Swift_LogFileTransport extends Swift_Transport_LogFileTransport /** * Create a new LogFileTransport. */ - public function __construct() + public function __construct(Swift_Events_EventDispatcher $eventDispatcher) { + parent::__construct($eventDispatcher); call_user_func_array( - array($this, 'Swift_Transport_LogFileTransport::__construct'), - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.null') + array($this, 'Swift_Transport_LogFileTransport::__construct'), + Swift_DependencyContainer::getInstance() + ->createDependenciesFor('transport.null') ); } diff --git a/css/ui-lightness/jqueryui.scss b/css/ui-lightness/jqueryui.scss index 418fee513..61ac91594 100644 --- a/css/ui-lightness/jqueryui.scss +++ b/css/ui-lightness/jqueryui.scss @@ -4,6 +4,8 @@ * To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=custom-theme&bgImgOpacityError=18&bgImgOpacityHighlight=75&bgImgOpacityActive=65&bgImgOpacityHover=100&bgImgOpacityDefault=100&bgImgOpacityContent=100&bgImgOpacityHeader=35&cornerRadiusShadow=5px&offsetLeftShadow=-5px&offsetTopShadow=-5px&thicknessShadow=5px&opacityShadow=20&bgImgOpacityShadow=10&bgTextureShadow=flat&bgColorShadow=%23000000&opacityOverlay=50&bgImgOpacityOverlay=20&bgTextureOverlay=diagonals_thick&bgColorOverlay=%23666666&iconColorError=%23ffd27a&fcError=%23ffffff&borderColorError=%23cd0a0a&bgTextureError=diagonals_thick&bgColorError=%23b81900&iconColorHighlight=%231c94c4&fcHighlight=%23363636&borderColorHighlight=%23fed22f&bgTextureHighlight=flat&bgColorHighlight=%23ffe45c&iconColorActive=%23E87C1E&fcActive=%23E87C1E&borderColorActive=%23E87C1E&bgTextureActive=flat&bgColorActive=%23ffffff&iconColorHover=%23E87C1E&fcHover=%23E87C1E&borderColorHover=%23E87C1E&bgTextureHover=flat&bgColorHover=%23fde17c&iconColorDefault=%23F26522&fcDefault=%23555555&borderColorDefault=%23cccccc&bgTextureDefault=flat&bgColorDefault=%23f1f1f1&iconColorContent=%23222222&fcContent=%23333333&borderColorContent=%23dddddd&bgTextureContent=flat&bgColorContent=%23eeeeee&iconColorHeader=%23ffffff&fcHeader=%23ffffff&borderColorHeader=%23F26522&bgTextureHeader=flat&bgColorHeader=%23E87C1E&cornerRadius=0&fwDefault=bold&fsDefault=1.1em&ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif * Copyright jQuery Foundation and other contributors; Licensed MIT * The original css file has been scssized (through www.css2scss.com) +* +* Other modification done : replaced the `Alpha(` by `alpha(` to avoid warnings generated by SCSSPHP */ .ui-draggable-handle { -ms-touch-action: none; @@ -46,26 +48,27 @@ } } .ui-helper-zfix { - width: 100%; - height: 100%; - top: 0; - left: 0; - position: absolute; - opacity: 0; - filter: Alpha(Opacity=0); + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter: alpha(Opacity=0); } .ui-front { z-index: 100; } .ui-state-disabled { - cursor: default !important; - pointer-events: none; - opacity: .35; - filter: Alpha(Opacity=35); - background-image: none; - .ui-icon { - filter: Alpha(Opacity=35); - } + cursor: default !important; + pointer-events: none; + opacity: .35; + filter: alpha(Opacity=35); + background-image: none; + + .ui-icon { + filter: alpha(Opacity=35); + } } .ui-icon { display: inline-block; @@ -93,7 +96,7 @@ height: 100%; // background: #666666 url($approot-relative + "css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=" + $version) 50% 50% repeat; opacity: .5; - filter: Alpha(Opacity=50); + filter: alpha(Opacity=50); } .ui-resizable { position: relative; @@ -1078,13 +1081,13 @@ body { } .ui-priority-secondary { opacity: .7; - filter: Alpha(Opacity=70); + filter: alpha(Opacity=70); //font-weight: normal; } .ui-state-disabled { - opacity: .35; - filter: Alpha(Opacity=35); - background-image: none; + opacity: .35; + filter: alpha(Opacity=35); + background-image: none; } .ui-icon { background-image: url($approot-relative + "css/ui-lightness/images/ui-icons_222222_256x240.png?v=" + $version); @@ -1148,13 +1151,13 @@ body { } .ui-priority-secondary { opacity: .7; - filter: Alpha(Opacity=70); + filter: alpha(Opacity=70); //font-weight: normal; } .ui-state-disabled { - opacity: .35; - filter: Alpha(Opacity=35); - background-image: none; + opacity: .35; + filter: alpha(Opacity=35); + background-image: none; } .ui-icon { background-image: url($approot-relative + "css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=" + $version); @@ -1362,7 +1365,7 @@ a { } .ui-priority-secondary { opacity: .7; - filter: Alpha(Opacity=70); + filter: alpha(Opacity=70); //font-weight: normal; } .ui-icon-blank { diff --git a/lib/autoload.php b/lib/autoload.php index 79c1600b5..64168f99a 100644 --- a/lib/autoload.php +++ b/lib/autoload.php @@ -2,6 +2,11 @@ // autoload.php @generated by Composer +if (PHP_VERSION_ID < 50600) { + echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; + exit(1); +} + require_once __DIR__ . '/composer/autoload_real.php'; return ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b::getLoader(); diff --git a/lib/bin/php-parse b/lib/bin/php-parse index e2e4c58a1..80f0e486d 100644 --- a/lib/bin/php-parse +++ b/lib/bin/php-parse @@ -4,21 +4,114 @@ /** * Proxy PHP file generated by Composer * - * This file includes the referenced bin path (../nikic/php-parser/bin/php-parse) using eval to remove the shebang if present + * This file includes the referenced bin path (../nikic/php-parser/bin/php-parse) + * using a stream wrapper to prevent the shebang from being output on PHP<8 * * @generated */ -$binPath = realpath(__DIR__ . "/" . '../nikic/php-parser/bin/php-parse'); -$contents = file_get_contents($binPath); -$contents = preg_replace('{^#!/.+\r?\n<\?(php)?}', '', $contents, 1, $replaced); -if ($replaced) { - $contents = strtr($contents, array( - '__FILE__' => var_export($binPath, true), - '__DIR__' => var_export(dirname($binPath), true), - )); +namespace Composer; - eval($contents); - exit(0); +$GLOBALS['_composer_bin_dir'] = __DIR__; +$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php'; + +if (PHP_VERSION_ID < 80000) { + if (!class_exists('Composer\BinProxyWrapper')) { + /** + * @internal + */ + final class BinProxyWrapper + { + private $handle; + private $position; + private $realpath; + + public function stream_open($path, $mode, $options, &$opened_path) + { + // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution + $opened_path = substr($path, 17); + $this->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 $binPath; + +include __DIR__ . '/..'.'/nikic/php-parser/bin/php-parse'; diff --git a/lib/bin/php-parse.bat b/lib/bin/php-parse.bat index a5baa4eda..2c5096dc3 100644 --- a/lib/bin/php-parse.bat +++ b/lib/bin/php-parse.bat @@ -1,4 +1,5 @@ @ECHO OFF setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0/../nikic/php-parser/bin/php-parse +SET BIN_TARGET=%~dp0/php-parse +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 php "%BIN_TARGET%" %* diff --git a/lib/bin/pscss b/lib/bin/pscss index 2879dcb97..f563d0cae 100644 --- a/lib/bin/pscss +++ b/lib/bin/pscss @@ -1,14 +1,117 @@ -#!/usr/bin/env sh +#!/usr/bin/env php + /dev/null; cd "../scssphp/scssphp/bin" && pwd) +/** + * Proxy PHP file generated by Composer + * + * This file includes the referenced bin path (../scssphp/scssphp/bin/pscss) + * using a stream wrapper to prevent the shebang from being output on PHP<8 + * + * @generated + */ -if [ -d /proc/cygdrive ]; then - case $(which php) in - $(readlink -n /proc/cygdrive)/*) - # We are in Cygwin using Windows php, so the path must be translated - dir=$(cygpath -m "$dir"); - ;; - esac -fi +namespace Composer; -"${dir}/pscss" "$@" +$GLOBALS['_composer_bin_dir'] = __DIR__; +$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php'; + +if (PHP_VERSION_ID < 80000) { + if (!class_exists('Composer\BinProxyWrapper')) { + /** + * @internal + */ + final class BinProxyWrapper + { + private $handle; + private $position; + private $realpath; + + public function stream_open($path, $mode, $options, &$opened_path) + { + // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution + $opened_path = substr($path, 17); + $this->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__ . '/..'.'/scssphp/scssphp/bin/pscss'); + exit(0); + } +} + +include __DIR__ . '/..'.'/scssphp/scssphp/bin/pscss'; diff --git a/lib/bin/pscss.bat b/lib/bin/pscss.bat index 1e368dc92..6b83bf27c 100644 --- a/lib/bin/pscss.bat +++ b/lib/bin/pscss.bat @@ -1,4 +1,5 @@ @ECHO OFF setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0/../scssphp/scssphp/bin/pscss +SET BIN_TARGET=%~dp0/pscss +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 php "%BIN_TARGET%" %* diff --git a/lib/combodo/tcpdf/.github/FUNDING.yml b/lib/combodo/tcpdf/.github/FUNDING.yml deleted file mode 100644 index ca5b4292e..000000000 --- a/lib/combodo/tcpdf/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20tcpdf%20project'] diff --git a/lib/combodo/tcpdf/.gitignore b/lib/combodo/tcpdf/.gitignore deleted file mode 100644 index 723ef36f4..000000000 --- a/lib/combodo/tcpdf/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea \ No newline at end of file diff --git a/lib/combodo/tcpdf/CHANGELOG.TXT b/lib/combodo/tcpdf/CHANGELOG.TXT index 3bdae3e24..e90bd161a 100644 --- a/lib/combodo/tcpdf/CHANGELOG.TXT +++ b/lib/combodo/tcpdf/CHANGELOG.TXT @@ -1,16 +1,129 @@ -6.2.25 +6.4.4 (2021-12-31) + - PHP 8.1 fixes + +6.4.3 (2021-12-28) + - Fix MultiCell PHPDoc typehint (#407) + - Fix type hint for \TCPDF_STATIC::_freadint (#414) + - Footer and Header font phpdoc fixes + constructor $pdfa phpdoc fix + setHeaderData lw param fix (#402) + - Fix text-annotation state options (#412) + - Fix - Named links have been broken. This fixes. (#415) + - Fixed type in comment for $lw header image logo width in mm + - Change Set to set. Fixes #419 (#421) + - Fix failing tests and failing tests not marking exit code as 1 (#426) + - Fix phpdoc and prefer null as default value (#444) + - Run on PHP 8.1 normally and add nightly PHP as allowed to fail (#452) + - Fix AES128 encryption if the OpenSSL extension is installed (#453) + - Explicitly cast values to int for imagesetpixel (#460) + - Fix cell_height_ratio type (#405) + - Leave &NBSP; lowercase when using text-transform (#403) + +6.4.2 (2021-07-20) + - Fix PHP 8.1 type error with TCPDF_STATIC::pregSplit on preg_split + - Fix a PHP array offset error + - Fixed phpdoc blocks + - Drop a PHP 4 polyfill and add a .gitattributes file + - Added a test-suite + - Removed pointless assignments + - Fix docblock spelling error + - Update version info + - Fix color being filled to type 0 with PHP 8 + - Fix warnings for undefined tags for $lineStyle + - Normalized composer.json + - Allowed transparency in PDF/A-2 and PDF/A-3 + - Add a TCPDF composer example + - Fixed implicit conversion from float to int for PHP 8.1 + - Removed status.txt from font directories, because of filesize + - Fixed type hints + - Removed "U" modifier from regexes + +6.4.1 (2021-03-27) + - Update tcpdf version (no code changes) + +6.4.0 (2021-03-27) + - allow styles on
tags + - check if file exists before calling unlink + - Fix image file type for urls with query params + - Fix SVGPath should accept 1.19.30 (equiv 1.19,.30) compacted values list + - Fix Second parameter of TCPDF::cell() must be a number + - PHP 8.0 function signature fixes + - Fix vulnerability to roman numeral bombs + - Optimized a regular expression + - Cache file get contents calls + - Remove mb_internal encoding handling + +6.3.5 (2020-02-14) + - Fixed curly braces in pdf417 + - Fixed a syntax error issue when accessing an index of a casted variable + +6.3.4 (2020-02-12) + - Check if imagekeys exist + - Unlink only images in cache + +6.3.3 (2020-02-12) + - Fixed PHP 7.4 - cannot use array offset on integers + - Fixed PDF/A-3B validation issue caused by missing pdfaSchema:property. + - Removed backup changelog files from repo + - Prevents the deletion of non-existent files in /tmp + - Prevent crash in case of no list access in cache path + - Check existence of file before delete it + - Fixed erase users pictures + - Fixed problem with $imagekeys undefined or unlinked + - Fix SVGPath elliptical arc with rx/ry=0 + z should return to initial point + - Fixed PHP 7.4 errors + - handle integers for pages + - Fixed background image doesn't work in RTL + - Fixed PDF/A validity + - Fixed datamatrix.php for PHP 7.4 + - Fixed deprecated PHP features + +6.3.2 (2019-09-20) + - Update ICC profile + +6.3.1 (2019-09-20) + - Fix reported version + - Fix Undefined property: GLPIPDF::$imagekeys + +6.3.0 (2019-09-19) + - fix SpotColor handling in HTML + - Add an additional empty test to prevent error in PHP 7.2 + - Fix the documentation how to calculate the cell height + - Drop duplicated array indices + - Fix TCPDF_STATIC::fileGetContents() + - Introduce other version of pdfA (2 and 3) + - Add UF and AFRelationship missing + - Fix performance issue of cloned instances + - Change glob to readdir which performs better + - URI in PDF can result in E_NOTICE + - Fix a warning for PHP 7.4 + - Fixed gradient offsets for percentage-based stops. + - Fixed file_get_contents return value should also be checked for a non-empty string + - Fix Array and string offset access syntax with curly braces is deprecated + - Fix PHP Warning: chr() expects parameter 1 to be int + - Add a VERSION file + +6.2.26 (2018-10-16) + - Update sRGB.icc with the one from the Debian package icc-profiles-free + - Fix unsupported operand types error when codepoints arrays are merged + +6.2.25 (2018-09-23) - Fix support for image URLs. 6.2.24 - Support remote urls when checking if file exists. -6.2.23 +6.2.23 (2018-09-22) - Simplify file_exists function. -6.2.22 +6.2.22 (2018-09-14) + - Fixes on `include/tcpdf_images.php`, `include/tcpdf_static.php` and `tcpdf.php` about file handling + +6.2.21 (2018-09-14) + - _no code changes_ + +6.2.20 (2018-09-14) - Fix for security vulnerability: Using the phar:// wrapper it was possible to trigger the unserialization of user provided data. -6.2.19 +6.2.19 (2018-09-14) - Merge various fixes for PHP 7.3 compatibility and security. 6.2.13 (2016-06-10) diff --git a/lib/combodo/tcpdf/README.md b/lib/combodo/tcpdf/README.md index db0149f69..0fb94009b 100644 --- a/lib/combodo/tcpdf/README.md +++ b/lib/combodo/tcpdf/README.md @@ -6,7 +6,7 @@ * **category** Library * **author** Nicola Asuni -* **copyright** 2002-2020 Nicola Asuni - Tecnick.com LTD +* **copyright** 2002-2021 Nicola Asuni - Tecnick.com LTD * **license** http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT) * **link** http://www.tcpdf.org * **source** https://github.com/tecnickcom/TCPDF diff --git a/lib/combodo/tcpdf/VERSION b/lib/combodo/tcpdf/VERSION index b98d1d3fa..49df80bfe 100644 --- a/lib/combodo/tcpdf/VERSION +++ b/lib/combodo/tcpdf/VERSION @@ -1 +1 @@ -6.3.5 +6.4.4 diff --git a/lib/combodo/tcpdf/composer.json b/lib/combodo/tcpdf/composer.json index fe90ae9eb..b53dd6e7f 100644 --- a/lib/combodo/tcpdf/composer.json +++ b/lib/combodo/tcpdf/composer.json @@ -3,9 +3,19 @@ "replace": { "tecnickcom/tcpdf": "self.version" }, - "homepage": "https://github.com/combodo-itop-libs/TCPDF", "type": "library", - "description": "TCPDF fork adding requirements for iTop: Specific fonts.", + "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", + "keywords": [ + "PDF", + "tcpdf", + "PDFD32000-2008", + "qrcode", + "datamatrix", + "pdf417", + "barcodes" + ], + "homepage": "https://github.com/combodo-itop-libs/TCPDF", + "version": "6.4.4", "license": "LGPL-3.0-only", "authors": [ { diff --git a/lib/combodo/tcpdf/include/barcodes/datamatrix.php b/lib/combodo/tcpdf/include/barcodes/datamatrix.php index 783f99da4..38bd625f7 100644 --- a/lib/combodo/tcpdf/include/barcodes/datamatrix.php +++ b/lib/combodo/tcpdf/include/barcodes/datamatrix.php @@ -229,7 +229,7 @@ class Datamatrix { /** * This is the class constructor. * Creates a datamatrix object - * @param $code (string) Code to represent using Datamatrix. + * @param string $code Code to represent using Datamatrix. * @public */ public function __construct($code) { @@ -355,11 +355,11 @@ class Datamatrix { /** * Product of two numbers in a Power-of-Two Galois Field - * @param $a (int) first number to multiply. - * @param $b (int) second number to multiply. - * @param $log (array) Log table. - * @param $alog (array) Anti-Log table. - * @param $gf (array) Number of Factors of the Reed-Solomon polynomial. + * @param int $a first number to multiply. + * @param int $b second number to multiply. + * @param array $log Log table. + * @param array $alog Anti-Log table. + * @param int $gf Number of Factors of the Reed-Solomon polynomial. * @return int product * @protected */ @@ -372,12 +372,12 @@ class Datamatrix { /** * Add error correction codewords to data codewords array (ANNEX E). - * @param $wd (array) Array of datacodewords. - * @param $nb (int) Number of blocks. - * @param $nd (int) Number of data codewords per block. - * @param $nc (int) Number of correction codewords per block. - * @param $gf (int) numner of fields on log/antilog table (power of 2). - * @param $pp (int) The value of its prime modulus polynomial (301 for ECC200). + * @param array $wd Array of datacodewords. + * @param int $nb Number of blocks. + * @param int $nd Number of data codewords per block. + * @param int $nc Number of correction codewords per block. + * @param int $gf numner of fields on log/antilog table (power of 2). + * @param int $pp The value of its prime modulus polynomial (301 for ECC200). * @return array data codewords + error codewords * @protected */ @@ -438,9 +438,9 @@ class Datamatrix { /** * Return the 253-state codeword - * @param $cwpad (int) Pad codeword. - * @param $cwpos (int) Number of data codewords from the beginning of encoded data. - * @return pad codeword + * @param int $cwpad Pad codeword. + * @param int $cwpos Number of data codewords from the beginning of encoded data. + * @return int pad codeword * @protected */ protected function get253StateCodeword($cwpad, $cwpos) { @@ -453,9 +453,9 @@ class Datamatrix { /** * Return the 255-state codeword - * @param $cwpad (int) Pad codeword. - * @param $cwpos (int) Number of data codewords from the beginning of encoded data. - * @return pad codeword + * @param int $cwpad Pad codeword. + * @param int $cwpos Number of data codewords from the beginning of encoded data. + * @return int pad codeword * @protected */ protected function get255StateCodeword($cwpad, $cwpos) { @@ -468,8 +468,8 @@ class Datamatrix { /** * Returns true if the char belongs to the selected mode - * @param $chr (int) Character (byte) to check. - * @param $mode (int) Current encoding mode. + * @param int $chr Character (byte) to check. + * @param int $mode Current encoding mode. * @return boolean true if the char is of the selected mode. * @protected */ @@ -514,9 +514,9 @@ class Datamatrix { /** * The look-ahead test scans the data to be encoded to find the best mode (Annex P - steps from J to S). - * @param $data (string) data to encode - * @param $pos (int) current position - * @param $mode (int) current encoding mode + * @param string $data data to encode + * @param int $pos current position + * @param int $mode current encoding mode * @return int encoding mode * @protected */ @@ -646,8 +646,8 @@ class Datamatrix { /** * Get the switching codeword to a new encoding mode (latch codeword) - * @param $mode (int) New encoding mode. - * @return (int) Switch codeword. + * @param int $mode New encoding mode. + * @return int Switch codeword. * @protected */ protected function getSwitchEncodingCodeword($mode) { @@ -685,8 +685,8 @@ class Datamatrix { /** * Choose the minimum matrix size and return the max number of data codewords. - * @param $numcw (int) Number of current codewords. - * @return number of data codewords in matrix + * @param int $numcw Number of current codewords. + * @return int number of data codewords in matrix * @protected */ protected function getMaxDataCodewords($numcw) { @@ -700,7 +700,7 @@ class Datamatrix { /** * Get high level encoding using the minimum symbol data characters for ECC 200 - * @param $data (string) data to encode + * @param string $data data to encode * @return array of codewords * @protected */ @@ -970,13 +970,13 @@ class Datamatrix { /** * Places "chr+bit" with appropriate wrapping within array[]. * (Annex F - ECC 200 symbol character placement) - * @param $marr (array) Array of symbols. - * @param $nrow (int) Number of rows. - * @param $ncol (int) Number of columns. - * @param $row (int) Row number. - * @param $col (int) Column number. - * @param $chr (int) Char byte. - * @param $bit (int) Bit. + * @param array $marr Array of symbols. + * @param int $nrow Number of rows. + * @param int $ncol Number of columns. + * @param int $row Row number. + * @param int $col Column number. + * @param int $chr Char byte. + * @param int $bit Bit. * @return array * @protected */ @@ -996,12 +996,12 @@ class Datamatrix { /** * Places the 8 bits of a utah-shaped symbol character. * (Annex F - ECC 200 symbol character placement) - * @param $marr (array) Array of symbols. - * @param $nrow (int) Number of rows. - * @param $ncol (int) Number of columns. - * @param $row (int) Row number. - * @param $col (int) Column number. - * @param $chr (int) Char byte. + * @param array $marr Array of symbols. + * @param int $nrow Number of rows. + * @param int $ncol Number of columns. + * @param int $row Row number. + * @param int $col Column number. + * @param int $chr Char byte. * @return array * @protected */ @@ -1020,10 +1020,10 @@ class Datamatrix { /** * Places the 8 bits of the first special corner case. * (Annex F - ECC 200 symbol character placement) - * @param $marr (array) Array of symbols. - * @param $nrow (int) Number of rows. - * @param $ncol (int) Number of columns. - * @param $chr (int) Char byte. + * @param array $marr Array of symbols. + * @param int $nrow Number of rows. + * @param int $ncol Number of columns. + * @param int $chr Char byte. * @return array * @protected */ @@ -1042,10 +1042,10 @@ class Datamatrix { /** * Places the 8 bits of the second special corner case. * (Annex F - ECC 200 symbol character placement) - * @param $marr (array) Array of symbols. - * @param $nrow (int) Number of rows. - * @param $ncol (int) Number of columns. - * @param $chr (int) Char byte. + * @param array $marr Array of symbols. + * @param int $nrow Number of rows. + * @param int $ncol Number of columns. + * @param int $chr Char byte. * @return array * @protected */ @@ -1064,10 +1064,10 @@ class Datamatrix { /** * Places the 8 bits of the third special corner case. * (Annex F - ECC 200 symbol character placement) - * @param $marr (array) Array of symbols. - * @param $nrow (int) Number of rows. - * @param $ncol (int) Number of columns. - * @param $chr (int) Char byte. + * @param array $marr Array of symbols. + * @param int $nrow Number of rows. + * @param int $ncol Number of columns. + * @param int $chr Char byte. * @return array * @protected */ @@ -1086,10 +1086,10 @@ class Datamatrix { /** * Places the 8 bits of the fourth special corner case. * (Annex F - ECC 200 symbol character placement) - * @param $marr (array) Array of symbols. - * @param $nrow (int) Number of rows. - * @param $ncol (int) Number of columns. - * @param $chr (int) Char byte. + * @param array $marr Array of symbols. + * @param int $nrow Number of rows. + * @param int $ncol Number of columns. + * @param int $chr Char byte. * @return array * @protected */ @@ -1108,8 +1108,8 @@ class Datamatrix { /** * Build a placement map. * (Annex F - ECC 200 symbol character placement) - * @param $nrow (int) Number of rows. - * @param $ncol (int) Number of columns. + * @param int $nrow Number of rows. + * @param int $ncol Number of columns. * @return array * @protected */ diff --git a/lib/combodo/tcpdf/include/barcodes/pdf417.php b/lib/combodo/tcpdf/include/barcodes/pdf417.php index 9a58a21f6..742802e1f 100644 --- a/lib/combodo/tcpdf/include/barcodes/pdf417.php +++ b/lib/combodo/tcpdf/include/barcodes/pdf417.php @@ -523,10 +523,10 @@ class PDF417 { /** * This is the class constructor. * Creates a PDF417 object - * @param $code (string) code to represent using PDF417 - * @param $ecl (int) error correction level (0-8); default -1 = automatic correction level - * @param $aspectratio (float) the width to height of the symbol (excluding quiet zones) - * @param $macro (array) information for macro block + * @param string $code code to represent using PDF417 + * @param int $ecl error correction level (0-8); default -1 = automatic correction level + * @param float $aspectratio the width to height of the symbol (excluding quiet zones) + * @param array $macro information for macro block * @public */ public function __construct($code, $ecl=-1, $aspectratio=2, $macro=array()) { @@ -734,12 +734,13 @@ class PDF417 { /** * Returns the error correction level (0-8) to be used - * @param $ecl (int) error correction level - * @param $numcw (int) number of data codewords + * @param int $ecl error correction level + * @param int $numcw number of data codewords * @return int error correction level * @protected */ protected function getErrorCorrectionLevel($ecl, $numcw) { + $maxecl = 8; // starting error level // check for automatic levels if (($ecl < 0) OR ($ecl > 8)) { if ($numcw < 41) { @@ -755,7 +756,6 @@ class PDF417 { } } // get maximum correction level - $maxecl = 8; // starting error level $maxerrsize = (928 - $numcw); // available codewords for error while ($maxecl > 0) { $errsize = (2 << $ecl); @@ -772,8 +772,8 @@ class PDF417 { /** * Returns the error correction codewords - * @param $cw (array) array of codewords including Symbol Length Descriptor and pad - * @param $ecl (int) error correction level 0-8 + * @param array $cw array of codewords including Symbol Length Descriptor and pad + * @param int $ecl error correction level 0-8 * @return array of error correction codewords * @protected */ @@ -809,8 +809,8 @@ class PDF417 { /** * Create array of sequences from input - * @param $code (string) code - * @return bidimensional array containing characters and classification + * @param string $code code + * @return array bi-dimensional array containing characters and classification * @protected */ protected function getInputSequences($code) { @@ -864,9 +864,9 @@ class PDF417 { /** * Compact data by mode. - * @param $mode (int) compaction mode number - * @param $code (string) data to compact - * @param $addmode (boolean) if true add the mode codeword at first position + * @param int $mode compaction mode number + * @param string $code data to compact + * @param boolean $addmode if true add the mode codeword at first position * @return array of codewords * @protected */ diff --git a/lib/combodo/tcpdf/include/barcodes/qrcode.php b/lib/combodo/tcpdf/include/barcodes/qrcode.php index 7ef2759fd..2e7f2f576 100644 --- a/lib/combodo/tcpdf/include/barcodes/qrcode.php +++ b/lib/combodo/tcpdf/include/barcodes/qrcode.php @@ -247,32 +247,6 @@ if (!defined('QRCODEDEFS')) { } // end of definitions -// #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# - -// for compatibility with PHP4 -if (!function_exists('str_split')) { - /** - * Convert a string to an array (needed for PHP4 compatibility) - * @param $string (string) The input string. - * @param $split_length (int) Maximum length of the chunk. - * @return If the optional split_length parameter is specified, the returned array will be broken down into chunks with each being split_length in length, otherwise each chunk will be one character in length. FALSE is returned if split_length is less than 1. If the split_length length exceeds the length of string , the entire string is returned as the first (and only) array element. - */ - function str_split($string, $split_length=1) { - if ((strlen($string) > $split_length) OR (!$split_length)) { - do { - $c = strlen($string); - $parts[] = substr($string, 0, $split_length); - $string = substr($string, $split_length); - } while ($string !== false); - } else { - $parts = array($string); - } - return $parts; - } -} - -// ##################################################### - /** * @class QRcode * Class to create QR-code arrays for TCPDF class. @@ -631,8 +605,8 @@ class QRcode { /** * This is the class constructor. * Creates a QRcode object - * @param $code (string) code to represent using QRcode - * @param $eclevel (string) error level: + * @param string $code code to represent using QRcode + * @param string $eclevel error level: * @public * @since 1.0.000 */ @@ -683,7 +657,7 @@ class QRcode { /** * Convert the frame in binary form - * @param $frame (array) array to binarize + * @param array $frame array to binarize * @return array frame in binary form */ protected function binarize($frame) { @@ -699,7 +673,7 @@ class QRcode { /** * Encode the input string to QR code - * @param $string (string) input string to encode + * @param string $string input string to encode */ protected function encodeString($string) { $this->dataStr = $string; @@ -715,7 +689,7 @@ class QRcode { /** * Encode mask - * @param $mask (int) masking mode + * @param int $mask masking mode */ protected function encodeMask($mask) { $spec = array(0, 0, 0, 0, 0); @@ -780,8 +754,8 @@ class QRcode { /** * Set frame value at specified position - * @param $at (array) x,y position - * @param $val (int) value of the character to set + * @param array $at x,y position + * @param int $val value of the character to set */ protected function setFrameAt($at, $val) { $this->frame[$at['y']][$at['x']] = chr($val); @@ -789,7 +763,7 @@ class QRcode { /** * Get frame value at specified position - * @param $at (array) x,y position + * @param array $at x,y position * @return value at specified position */ protected function getFrameAt($at) { @@ -853,8 +827,8 @@ class QRcode { /** * Initialize code. - * @param $spec (array) array of ECC specification - * @return 0 in case of success, -1 in case of error + * @param array $spec array of ECC specification + * @return int 0 in case of success, -1 in case of error */ protected function init($spec) { $dl = $this->rsDataCodes1($spec); @@ -932,10 +906,10 @@ class QRcode { /** * Write Format Information on frame and returns the number of black bits - * @param $width (int) frame width - * @param $frame (array) frame - * @param $mask (array) masking mode - * @param $level (int) error correction level + * @param int $width frame width + * @param array $frame frame + * @param array $mask masking mode + * @param int $level error correction level * @return int blacks */ protected function writeFormatInformation($width, &$frame, $mask, $level) { @@ -976,8 +950,8 @@ class QRcode { /** * mask0 - * @param $x (int) X position - * @param $y (int) Y position + * @param int $x X position + * @param int $y Y position * @return int mask */ protected function mask0($x, $y) { @@ -986,8 +960,8 @@ class QRcode { /** * mask1 - * @param $x (int) X position - * @param $y (int) Y position + * @param int $x X position + * @param int $y Y position * @return int mask */ protected function mask1($x, $y) { @@ -996,8 +970,8 @@ class QRcode { /** * mask2 - * @param $x (int) X position - * @param $y (int) Y position + * @param int $x X position + * @param int $y Y position * @return int mask */ protected function mask2($x, $y) { @@ -1006,8 +980,8 @@ class QRcode { /** * mask3 - * @param $x (int) X position - * @param $y (int) Y position + * @param int $x X position + * @param int $y Y position * @return int mask */ protected function mask3($x, $y) { @@ -1016,8 +990,8 @@ class QRcode { /** * mask4 - * @param $x (int) X position - * @param $y (int) Y position + * @param int $x X position + * @param int $y Y position * @return int mask */ protected function mask4($x, $y) { @@ -1026,8 +1000,8 @@ class QRcode { /** * mask5 - * @param $x (int) X position - * @param $y (int) Y position + * @param int $x X position + * @param int $y Y position * @return int mask */ protected function mask5($x, $y) { @@ -1036,8 +1010,8 @@ class QRcode { /** * mask6 - * @param $x (int) X position - * @param $y (int) Y position + * @param int $x X position + * @param int $y Y position * @return int mask */ protected function mask6($x, $y) { @@ -1046,8 +1020,8 @@ class QRcode { /** * mask7 - * @param $x (int) X position - * @param $y (int) Y position + * @param int $x X position + * @param int $y Y position * @return int mask */ protected function mask7($x, $y) { @@ -1056,9 +1030,9 @@ class QRcode { /** * Return bitmask - * @param $maskNo (int) mask number - * @param $width (int) width - * @param $frame (array) frame + * @param int $maskNo mask number + * @param int $width width + * @param array $frame frame * @return array bitmask */ protected function generateMaskNo($maskNo, $width, $frame) { @@ -1078,11 +1052,11 @@ class QRcode { /** * makeMaskNo - * @param $maskNo (int) - * @param $width (int) - * @param $s (int) - * @param $d (int) - * @param $maskGenOnly (boolean) + * @param int $maskNo + * @param int $width + * @param int $s + * @param int $d + * @param boolean $maskGenOnly * @return int b */ protected function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly=false) { @@ -1106,10 +1080,10 @@ class QRcode { /** * makeMask - * @param $width (int) - * @param $frame (array) - * @param $maskNo (int) - * @param $level (int) + * @param int $width + * @param array $frame + * @param int $maskNo + * @param int $level * @return array mask */ protected function makeMask($width, $frame, $maskNo, $level) { @@ -1121,7 +1095,7 @@ class QRcode { /** * calcN1N3 - * @param $length (int) + * @param int $length * @return int demerit */ protected function calcN1N3($length) { @@ -1151,8 +1125,8 @@ class QRcode { /** * evaluateSymbol - * @param $width (int) - * @param $frame (array) + * @param int $width + * @param array $frame * @return int demerit */ protected function evaluateSymbol($width, $frame) { @@ -1212,9 +1186,9 @@ class QRcode { /** * mask - * @param $width (int) - * @param $frame (array) - * @param $level (int) + * @param int $width + * @param array $frame + * @param int $level * @return array best mask */ protected function mask($width, $frame, $level) { @@ -1255,8 +1229,8 @@ class QRcode { /** * Return true if the character at specified position is a number - * @param $str (string) string - * @param $pos (int) characted position + * @param string $str string + * @param int $pos characted position * @return boolean true of false */ protected function isdigitat($str, $pos) { @@ -1268,8 +1242,8 @@ class QRcode { /** * Return true if the character at specified position is an alphanumeric character - * @param $str (string) string - * @param $pos (int) characted position + * @param string $str string + * @param int $pos characted position * @return boolean true of false */ protected function isalnumat($str, $pos) { @@ -1281,7 +1255,7 @@ class QRcode { /** * identifyMode - * @param $pos (int) + * @param int $pos * @return int mode */ protected function identifyMode($pos) { @@ -1386,6 +1360,7 @@ class QRcode { $p += 2; } $this->items = $this->appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr)); + $run = $p; return $run; } @@ -1440,7 +1415,7 @@ class QRcode { /** * splitString - * @return (int) + * @return int */ protected function splitString() { while (strlen($this->dataStr) > 0) { @@ -1455,7 +1430,7 @@ class QRcode { break; } case QR_MODE_KJ: { - if ($hint == QR_MODE_KJ) { + if ($this->hint == QR_MODE_KJ) { $length = $this->eatKanji(); } else { $length = $this->eat8(); @@ -1504,10 +1479,10 @@ class QRcode { /** * newInputItem - * @param $mode (int) - * @param $size (int) - * @param $data (array) - * @param $bstream (array) + * @param int $mode + * @param int $size + * @param array $data + * @param array $bstream * @return array input item */ protected function newInputItem($mode, $size, $data, $bstream=null) { @@ -1528,8 +1503,8 @@ class QRcode { /** * encodeModeNum - * @param $inputitem (array) - * @param $version (int) + * @param array $inputitem + * @param int $version * @return array input item */ protected function encodeModeNum($inputitem, $version) { @@ -1557,8 +1532,8 @@ class QRcode { /** * encodeModeAn - * @param $inputitem (array) - * @param $version (int) + * @param array $inputitem + * @param int $version * @return array input item */ protected function encodeModeAn($inputitem, $version) { @@ -1580,8 +1555,8 @@ class QRcode { /** * encodeMode8 - * @param $inputitem (array) - * @param $version (int) + * @param array $inputitem + * @param int $version * @return array input item */ protected function encodeMode8($inputitem, $version) { @@ -1596,8 +1571,8 @@ class QRcode { /** * encodeModeKanji - * @param $inputitem (array) - * @param $version (int) + * @param array $inputitem + * @param int $version * @return array input item */ protected function encodeModeKanji($inputitem, $version) { @@ -1620,7 +1595,7 @@ class QRcode { /** * encodeModeStructure - * @param $inputitem (array) + * @param array $inputitem * @return array input item */ protected function encodeModeStructure($inputitem) { @@ -1634,8 +1609,8 @@ class QRcode { /** * encodeBitStream - * @param $inputitem (array) - * @param $version (int) + * @param array $inputitem + * @param int $version * @return array input item */ protected function encodeBitStream($inputitem, $version) { @@ -1686,11 +1661,11 @@ class QRcode { /** * Append data to an input object. * The data is copied and appended to the input object. - * @param $items (arrray) input items - * @param $mode (int) encoding mode. - * @param $size (int) size of data (byte). - * @param $data (array) array of input data. - * @return items + * @param array $items input items + * @param int $mode encoding mode. + * @param int $size size of data (byte). + * @param array $data array of input data. + * @return array items * */ protected function appendNewInputItem($items, $mode, $size, $data) { @@ -1703,10 +1678,10 @@ class QRcode { /** * insertStructuredAppendHeader - * @param $items (array) - * @param $size (int) - * @param $index (int) - * @param $parity (int) + * @param array $items + * @param int $size + * @param int $index + * @param int $parity * @return array items */ protected function insertStructuredAppendHeader($items, $size, $index, $parity) { @@ -1724,7 +1699,7 @@ class QRcode { /** * calcParity - * @param $items (array) + * @param array $items * @return int parity */ protected function calcParity($items) { @@ -1741,8 +1716,8 @@ class QRcode { /** * checkModeNum - * @param $size (int) - * @param $data (array) + * @param int $size + * @param array $data * @return boolean true or false */ protected function checkModeNum($size, $data) { @@ -1755,9 +1730,9 @@ class QRcode { } /** - * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19). - * @param $c (int) character value - * @return value + * Look up the alphabet-numeric conversion table (see JIS X0510:2004, pp.19). + * @param int $c character value + * @return int value */ protected function lookAnTable($c) { return (($c > 127)?-1:$this->anTable[$c]); @@ -1765,8 +1740,8 @@ class QRcode { /** * checkModeAn - * @param $size (int) - * @param $data (array) + * @param int $size + * @param array $data * @return boolean true or false */ protected function checkModeAn($size, $data) { @@ -1780,7 +1755,7 @@ class QRcode { /** * estimateBitsModeNum - * @param $size (int) + * @param int $size * @return int number of bits */ protected function estimateBitsModeNum($size) { @@ -1801,7 +1776,7 @@ class QRcode { /** * estimateBitsModeAn - * @param $size (int) + * @param int $size * @return int number of bits */ protected function estimateBitsModeAn($size) { @@ -1814,7 +1789,7 @@ class QRcode { /** * estimateBitsMode8 - * @param $size (int) + * @param int $size * @return int number of bits */ protected function estimateBitsMode8($size) { @@ -1823,7 +1798,7 @@ class QRcode { /** * estimateBitsModeKanji - * @param $size (int) + * @param int $size * @return int number of bits */ protected function estimateBitsModeKanji($size) { @@ -1832,8 +1807,8 @@ class QRcode { /** * checkModeKanji - * @param $size (int) - * @param $data (array) + * @param int $size + * @param array $data * @return boolean true or false */ protected function checkModeKanji($size, $data) { @@ -1851,9 +1826,9 @@ class QRcode { /** * Validate the input data. - * @param $mode (int) encoding mode. - * @param $size (int) size of data (byte). - * @param $data (array) data to validate + * @param int $mode encoding mode. + * @param int $size size of data (byte). + * @param array $data data to validate * @return boolean true in case of valid data, false otherwise */ protected function check($mode, $size, $data) { @@ -1885,8 +1860,8 @@ class QRcode { /** * estimateBitStreamSize - * @param $items (array) - * @param $version (int) + * @param array $items + * @param int $version * @return int bits */ protected function estimateBitStreamSize($items, $version) { @@ -1929,7 +1904,7 @@ class QRcode { /** * estimateVersion - * @param $items (array) + * @param array $items * @return int version */ protected function estimateVersion($items) { @@ -1948,9 +1923,9 @@ class QRcode { /** * lengthOfCode - * @param $mode (int) - * @param $version (int) - * @param $bits (int) + * @param int $mode + * @param int $version + * @param int $bits * @return int size */ protected function lengthOfCode($mode, $version, $bits) { @@ -2005,7 +1980,7 @@ class QRcode { /** * createBitStream - * @param $items (array) + * @param array $items * @return array of items and total bits */ protected function createBitStream($items) { @@ -2020,7 +1995,7 @@ class QRcode { /** * convertData - * @param $items (array) + * @param array $items * @return array items */ protected function convertData($items) { @@ -2049,7 +2024,7 @@ class QRcode { /** * Append Padding Bit to bitstream - * @param $bstream (array) + * @param array $bstream * @return array bitstream */ protected function appendPaddingBit($bstream) { @@ -2082,7 +2057,7 @@ class QRcode { /** * mergeBitStream - * @param $items (array) items + * @param array $items items * @return array bitstream */ protected function mergeBitStream($items) { @@ -2099,7 +2074,7 @@ class QRcode { /** * Returns a stream of bits. - * @param $items (int) + * @param int $items * @return array padded merged byte stream */ protected function getBitStream($items) { @@ -2109,7 +2084,7 @@ class QRcode { /** * Pack all bit streams padding bits into a byte array. - * @param $items (int) + * @param int $items * @return array padded merged byte stream */ protected function getByteStream($items) { @@ -2123,7 +2098,7 @@ class QRcode { /** * Return an array with zeros - * @param $setLength (int) array size + * @param int $setLength array size * @return array */ protected function allocate($setLength) { @@ -2132,8 +2107,8 @@ class QRcode { /** * Return new bitstream from number - * @param $bits (int) number of bits - * @param $num (int) number + * @param int $bits number of bits + * @param int $num number * @return array bitstream */ protected function newFromNum($bits, $num) { @@ -2152,8 +2127,8 @@ class QRcode { /** * Return new bitstream from bytes - * @param $size (int) size - * @param $data (array) bytes + * @param int $size size + * @param array $data bytes * @return array bitstream */ protected function newFromBytes($size, $data) { @@ -2176,8 +2151,8 @@ class QRcode { /** * Append one bitstream to another - * @param $bitstream (array) original bitstream - * @param $append (array) bitstream to append + * @param array $bitstream original bitstream + * @param array $append bitstream to append * @return array bitstream */ protected function appendBitstream($bitstream, $append) { @@ -2192,9 +2167,9 @@ class QRcode { /** * Append one bitstream created from number to another - * @param $bitstream (array) original bitstream - * @param $bits (int) number of bits - * @param $num (int) number + * @param array $bitstream original bitstream + * @param int $bits number of bits + * @param int $num number * @return array bitstream */ protected function appendNum($bitstream, $bits, $num) { @@ -2207,9 +2182,9 @@ class QRcode { /** * Append one bitstream created from bytes to another - * @param $bitstream (array) original bitstream - * @param $size (int) size - * @param $data (array) bytes + * @param array $bitstream original bitstream + * @param int $size size + * @param array $data bytes * @return array bitstream */ protected function appendBytes($bitstream, $size, $data) { @@ -2222,7 +2197,7 @@ class QRcode { /** * Convert bitstream to bytes - * @param $bstream (array) original bitstream + * @param array $bstream original bitstream * @return array of bytes */ protected function bitstreamToByte($bstream) { @@ -2263,11 +2238,11 @@ class QRcode { /** * Replace a value on the array at the specified position - * @param $srctab (array) - * @param $x (int) X position - * @param $y (int) Y position - * @param $repl (string) value to replace - * @param $replLen (int) length of the repl string + * @param array $srctab + * @param int $x X position + * @param int $y Y position + * @param string $repl value to replace + * @param int $replLen length of the repl string * @return array srctab */ protected function qrstrset($srctab, $x, $y, $repl, $replLen=false) { @@ -2277,8 +2252,8 @@ class QRcode { /** * Return maximum data code length (bytes) for the version. - * @param $version (int) version - * @param $level (int) error correction level + * @param int $version version + * @param int $level error correction level * @return int maximum size (bytes) */ protected function getDataLength($version, $level) { @@ -2287,8 +2262,8 @@ class QRcode { /** * Return maximum error correction code length (bytes) for the version. - * @param $version (int) version - * @param $level (int) error correction level + * @param int $version version + * @param int $level error correction level * @return int ECC size (bytes) */ protected function getECCLength($version, $level){ @@ -2297,7 +2272,7 @@ class QRcode { /** * Return the width of the symbol for the version. - * @param $version (int) version + * @param int $version version * @return int width */ protected function getWidth($version) { @@ -2306,7 +2281,7 @@ class QRcode { /** * Return the numer of remainder bits. - * @param $version (int) version + * @param int $version version * @return int number of remainder bits */ protected function getRemainder($version) { @@ -2315,8 +2290,8 @@ class QRcode { /** * Return a version number that satisfies the input code length. - * @param $size (int) input code length (bytes) - * @param $level (int) error correction level + * @param int $size input code length (bytes) + * @param int $level error correction level * @return int version number */ protected function getMinimumVersion($size, $level) { @@ -2332,8 +2307,8 @@ class QRcode { /** * Return the size of length indicator for the mode and version. - * @param $mode (int) encoding mode - * @param $version (int) version + * @param int $mode encoding mode + * @param int $version version * @return int the size of the appropriate length indicator (bits). */ protected function lengthIndicator($mode, $version) { @@ -2352,8 +2327,8 @@ class QRcode { /** * Return the maximum length for the mode and version. - * @param $mode (int) encoding mode - * @param $version (int) version + * @param int $mode encoding mode + * @param int $version version * @return int the maximum length (bytes) */ protected function maximumWords($mode, $version) { @@ -2377,9 +2352,9 @@ class QRcode { /** * Return an array of ECC specification. - * @param $version (int) version - * @param $level (int) error correction level - * @param $spec (array) an array of ECC specification contains as following: {# of type1 blocks, # of data code, # of ecc code, # of type2 blocks, # of data code} + * @param int $version version + * @param int $level error correction level + * @param array $spec an array of ECC specification contains as following: {# of type1 blocks, # of data code, # of ecc code, # of type2 blocks, # of data code} * @return array spec */ protected function getEccSpec($version, $level, $spec) { @@ -2408,9 +2383,9 @@ class QRcode { /** * Put an alignment marker. - * @param $frame (array) frame - * @param $ox (int) X center coordinate of the pattern - * @param $oy (int) Y center coordinate of the pattern + * @param array $frame frame + * @param int $ox X center coordinate of the pattern + * @param int $oy Y center coordinate of the pattern * @return array frame */ protected function putAlignmentMarker($frame, $ox, $oy) { @@ -2431,9 +2406,9 @@ class QRcode { /** * Put an alignment pattern. - * @param $version (int) version - * @param $frame (array) frame - * @param $width (int) width + * @param int $version version + * @param array $frame frame + * @param int $width width * @return array frame */ protected function putAlignmentPattern($version, $frame, $width) { @@ -2473,8 +2448,8 @@ class QRcode { /** * Return BCH encoded version information pattern that is used for the symbol of version 7 or greater. Use lower 18 bits. - * @param $version (int) version - * @return BCH encoded version information pattern + * @param int $version version + * @return string BCH encoded version information pattern */ protected function getVersionPattern($version) { if (($version < 7) OR ($version > QRSPEC_VERSION_MAX)) { @@ -2485,9 +2460,9 @@ class QRcode { /** * Return BCH encoded format information pattern. - * @param $mask (array) - * @param $level (int) error correction level - * @return BCH encoded format information pattern + * @param array $mask + * @param int $level error correction level + * @return string BCH encoded format information pattern */ protected function getFormatInfo($mask, $level) { if (($mask < 0) OR ($mask > 7)) { @@ -2501,9 +2476,9 @@ class QRcode { /** * Put a finder pattern. - * @param $frame (array) frame - * @param $ox (int) X center coordinate of the pattern - * @param $oy (int) Y center coordinate of the pattern + * @param array $frame frame + * @param int $ox X center coordinate of the pattern + * @param int $oy Y center coordinate of the pattern * @return array frame */ protected function putFinderPattern($frame, $ox, $oy) { @@ -2524,8 +2499,8 @@ class QRcode { /** * Return a copy of initialized frame. - * @param $version (int) version - * @return Array of unsigned char. + * @param int $version version + * @return array array of unsigned char. */ protected function createFrame($version) { $width = $this->capacity[$version][QRCAP_WIDTH]; @@ -2589,8 +2564,8 @@ class QRcode { /** * Set new frame for the specified version. - * @param $version (int) version - * @return Array of unsigned char. + * @param int $version version + * @return array array of unsigned char. */ protected function newFrame($version) { if (($version < 1) OR ($version > QRSPEC_VERSION_MAX)) { @@ -2607,7 +2582,7 @@ class QRcode { /** * Return block number 0 - * @param $spec (array) + * @param array $spec * @return int value */ protected function rsBlockNum($spec) { @@ -2616,7 +2591,7 @@ class QRcode { /** * Return block number 1 - * @param $spec (array) + * @param array $spec * @return int value */ protected function rsBlockNum1($spec) { @@ -2625,7 +2600,7 @@ class QRcode { /** * Return data codes 1 - * @param $spec (array) + * @param array $spec * @return int value */ protected function rsDataCodes1($spec) { @@ -2634,7 +2609,7 @@ class QRcode { /** * Return ecc codes 1 - * @param $spec (array) + * @param array $spec * @return int value */ protected function rsEccCodes1($spec) { @@ -2643,7 +2618,7 @@ class QRcode { /** * Return block number 2 - * @param $spec (array) + * @param array $spec * @return int value */ protected function rsBlockNum2($spec) { @@ -2652,7 +2627,7 @@ class QRcode { /** * Return data codes 2 - * @param $spec (array) + * @param array $spec * @return int value */ protected function rsDataCodes2($spec) { @@ -2661,7 +2636,7 @@ class QRcode { /** * Return ecc codes 2 - * @param $spec (array) + * @param array $spec * @return int value */ protected function rsEccCodes2($spec) { @@ -2670,7 +2645,7 @@ class QRcode { /** * Return data length - * @param $spec (array) + * @param array $spec * @return int value */ protected function rsDataLength($spec) { @@ -2679,7 +2654,7 @@ class QRcode { /** * Return ecc length - * @param $spec (array) + * @param array $spec * @return int value */ protected function rsEccLength($spec) { @@ -2692,12 +2667,12 @@ class QRcode { /** * Initialize a Reed-Solomon codec and add it to existing rsitems - * @param $symsize (int) symbol size, bits - * @param $gfpoly (int) Field generator polynomial coefficients - * @param $fcr (int) first root of RS code generator polynomial, index form - * @param $prim (int) primitive element to generate polynomial roots - * @param $nroots (int) RS code generator polynomial degree (number of roots) - * @param $pad (int) padding bytes at front of shortened block + * @param int $symsize symbol size, bits + * @param int $gfpoly Field generator polynomial coefficients + * @param int $fcr first root of RS code generator polynomial, index form + * @param int $prim primitive element to generate polynomial roots + * @param int $nroots RS code generator polynomial degree (number of roots) + * @param int $pad padding bytes at front of shortened block * @return array Array of RS values:. */ protected function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) { @@ -2719,8 +2694,8 @@ class QRcode { /** * modnn - * @param $rs (array) RS values - * @param $x (int) X position + * @param array $rs RS values + * @param int $x X position * @return int X osition */ protected function modnn($rs, $x) { @@ -2733,12 +2708,12 @@ class QRcode { /** * Initialize a Reed-Solomon codec and returns an array of values. - * @param $symsize (int) symbol size, bits - * @param $gfpoly (int) Field generator polynomial coefficients - * @param $fcr (int) first root of RS code generator polynomial, index form - * @param $prim (int) primitive element to generate polynomial roots - * @param $nroots (int) RS code generator polynomial degree (number of roots) - * @param $pad (int) padding bytes at front of shortened block + * @param int $symsize symbol size, bits + * @param int $gfpoly Field generator polynomial coefficients + * @param int $fcr first root of RS code generator polynomial, index form + * @param int $prim primitive element to generate polynomial roots + * @param int $nroots RS code generator polynomial degree (number of roots) + * @param int $pad padding bytes at front of shortened block * @return array Array of RS values:. */ protected function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) { @@ -2820,9 +2795,9 @@ class QRcode { /** * Encode a Reed-Solomon codec and returns the parity array - * @param $rs (array) RS values - * @param $data (array) data - * @param $parity (array) parity + * @param array $rs RS values + * @param array $data data + * @param array $parity parity * @return parity array */ protected function encode_rs_char($rs, $data, $parity) { diff --git a/lib/combodo/tcpdf/include/tcpdf_colors.php b/lib/combodo/tcpdf/include/tcpdf_colors.php index 27fb7afd1..7f337f31a 100644 --- a/lib/combodo/tcpdf/include/tcpdf_colors.php +++ b/lib/combodo/tcpdf/include/tcpdf_colors.php @@ -240,9 +240,9 @@ class TCPDF_COLORS { /** * Return the Spot color array. - * @param $name (string) Name of the spot color. - * @param $spotc (array) Reference to an array of spot colors. - * @return (array) Spot color array or false if not defined. + * @param string $name Name of the spot color. + * @param array $spotc Reference to an array of spot colors. + * @return array|false Spot color array or false if not defined. * @since 5.9.125 (2011-10-03) * @public static */ @@ -264,10 +264,10 @@ class TCPDF_COLORS { /** * Returns an array (RGB or CMYK) from an html color name, or a six-digit (i.e. #3FE5AA), or three-digit (i.e. #7FF) hexadecimal color, or a javascript color array, or javascript color name. - * @param $hcolor (string) HTML color. - * @param $spotc (array) Reference to an array of spot colors. - * @param $defcol (array) Color to return in case of error. - * @return array RGB or CMYK color, or false in case of error. + * @param string $hcolor HTML color. + * @param array $spotc Reference to an array of spot colors. + * @param array $defcol Color to return in case of error. + * @return array|false RGB or CMYK color, or false in case of error. * @public static */ public static function convertHTMLColorToDec($hcolor, &$spotc, $defcol=array('R'=>128,'G'=>128,'B'=>128)) { @@ -407,8 +407,8 @@ class TCPDF_COLORS { /** * Convert a color array into a string representation. - * @param $c (array) Array of colors. - * @return (string) The color array representation. + * @param array $c Array of colors. + * @return string The color array representation. * @since 5.9.137 (2011-12-01) * @public static */ @@ -438,7 +438,7 @@ class TCPDF_COLORS { /** * Convert color to javascript color. - * @param $color (string) color name or "#RRGGBB" + * @param string $color color name or "#RRGGBB" * @protected * @since 2.1.002 (2008-02-12) * @public static @@ -449,7 +449,7 @@ class TCPDF_COLORS { } if (!in_array($color, self::$jscolor)) { // default transparent color - $color = $jscolor[0]; + $color = self::$jscolor[0]; } return 'color.'.$color; } diff --git a/lib/combodo/tcpdf/include/tcpdf_filters.php b/lib/combodo/tcpdf/include/tcpdf_filters.php index 3bb89c092..3009cff7c 100644 --- a/lib/combodo/tcpdf/include/tcpdf_filters.php +++ b/lib/combodo/tcpdf/include/tcpdf_filters.php @@ -60,7 +60,7 @@ class TCPDF_FILTERS { /** * Get a list of available decoding filters. - * @return (array) Array of available filter decoders. + * @return array Array of available filter decoders. * @since 1.0.000 (2011-05-23) * @public static */ @@ -70,9 +70,9 @@ class TCPDF_FILTERS { /** * Decode data using the specified filter type. - * @param $filter (string) Filter name. - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $filter Filter name. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -130,8 +130,8 @@ class TCPDF_FILTERS { /** * Standard * Default decoding filter (leaves data unchanged). - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -142,8 +142,8 @@ class TCPDF_FILTERS { /** * ASCIIHexDecode * Decodes data encoded in an ASCII hexadecimal representation, reproducing the original binary data. - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -182,8 +182,8 @@ class TCPDF_FILTERS { /** * ASCII85Decode * Decodes data encoded in an ASCII base-85 representation, reproducing the original binary data. - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -266,8 +266,8 @@ class TCPDF_FILTERS { /** * LZWDecode * Decompresses data encoded using the LZW (Lempel-Ziv-Welch) adaptive compression method, reproducing the original text or binary data. - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -347,8 +347,8 @@ class TCPDF_FILTERS { /** * FlateDecode * Decompresses data encoded using the zlib/deflate compression method, reproducing the original text or binary data. - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -364,7 +364,7 @@ class TCPDF_FILTERS { /** * RunLengthDecode * Decompresses data encoded using a byte-oriented run-length encoding algorithm. - * @param $data (string) Data to decode. + * @param string $data Data to decode. * @since 1.0.000 (2011-05-23) * @public static */ @@ -400,8 +400,8 @@ class TCPDF_FILTERS { /** * CCITTFaxDecode (NOT IMPLEMETED - RETURN AN EXCEPTION) * Decompresses data encoded using the CCITT facsimile standard, reproducing the original data (typically monochrome image data at 1 bit per pixel). - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -413,8 +413,8 @@ class TCPDF_FILTERS { /** * JBIG2Decode (NOT IMPLEMETED - RETURN AN EXCEPTION) * Decompresses data encoded using the JBIG2 standard, reproducing the original monochrome (1 bit per pixel) image data (or an approximation of that data). - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -426,8 +426,8 @@ class TCPDF_FILTERS { /** * DCTDecode (NOT IMPLEMETED - RETURN AN EXCEPTION) * Decompresses data encoded using a DCT (discrete cosine transform) technique based on the JPEG standard, reproducing image sample data that approximates the original data. - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -439,8 +439,8 @@ class TCPDF_FILTERS { /** * JPXDecode (NOT IMPLEMETED - RETURN AN EXCEPTION) * Decompresses data encoded using the wavelet-based JPEG2000 standard, reproducing the original image data. - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -452,8 +452,8 @@ class TCPDF_FILTERS { /** * Crypt (NOT IMPLEMETED - RETURN AN EXCEPTION) * Decrypts data encrypted by a security handler, reproducing the data as it was before encryption. - * @param $data (string) Data to decode. - * @return Decoded data string. + * @param string $data Data to decode. + * @return string Decoded data string. * @since 1.0.000 (2011-05-23) * @public static */ @@ -466,7 +466,7 @@ class TCPDF_FILTERS { /** * Throw an exception. - * @param $msg (string) The error message + * @param string $msg The error message * @since 1.0.000 (2011-05-23) * @public static */ diff --git a/lib/combodo/tcpdf/include/tcpdf_fonts.php b/lib/combodo/tcpdf/include/tcpdf_fonts.php index 218fb6df1..c692ef87d 100644 --- a/lib/combodo/tcpdf/include/tcpdf_fonts.php +++ b/lib/combodo/tcpdf/include/tcpdf_fonts.php @@ -55,16 +55,16 @@ class TCPDF_FONTS { /** * Convert and add the selected TrueType or Type1 font to the fonts folder (that must be writeable). - * @param $fontfile (string) Font file (full path). - * @param $fonttype (string) Font type. Leave empty for autodetect mode. Valid values are: TrueTypeUnicode, TrueType, Type1, CID0JP = CID-0 Japanese, CID0KR = CID-0 Korean, CID0CS = CID-0 Chinese Simplified, CID0CT = CID-0 Chinese Traditional. - * @param $enc (string) Name of the encoding table to use. Leave empty for default mode. Omit this parameter for TrueType Unicode and symbolic fonts like Symbol or ZapfDingBats. - * @param $flags (int) Unsigned 32-bit integer containing flags specifying various characteristics of the font (PDF32000:2008 - 9.8.2 Font Descriptor Flags): +1 for fixed font; +4 for symbol or +32 for non-symbol; +64 for italic. Fixed and Italic mode are generally autodetected so you have to set it to 32 = non-symbolic font (default) or 4 = symbolic font. - * @param $outpath (string) Output path for generated font files (must be writeable by the web server). Leave empty for default font folder. - * @param $platid (int) Platform ID for CMAP table to extract (when building a Unicode font for Windows this value should be 3, for Macintosh should be 1). - * @param $encid (int) Encoding ID for CMAP table to extract (when building a Unicode font for Windows this value should be 1, for Macintosh should be 0). When Platform ID is 3, legal values for Encoding ID are: 0=Symbol, 1=Unicode, 2=ShiftJIS, 3=PRC, 4=Big5, 5=Wansung, 6=Johab, 7=Reserved, 8=Reserved, 9=Reserved, 10=UCS-4. - * @param $addcbbox (boolean) If true includes the character bounding box information on the php font file. - * @param $link (boolean) If true link to system font instead of copying the font data (not transportable) - Note: do not work with Type1 fonts. - * @return (string) TCPDF font name or boolean false in case of error. + * @param string $fontfile Font file (full path). + * @param string $fonttype Font type. Leave empty for autodetect mode. Valid values are: TrueTypeUnicode, TrueType, Type1, CID0JP = CID-0 Japanese, CID0KR = CID-0 Korean, CID0CS = CID-0 Chinese Simplified, CID0CT = CID-0 Chinese Traditional. + * @param string $enc Name of the encoding table to use. Leave empty for default mode. Omit this parameter for TrueType Unicode and symbolic fonts like Symbol or ZapfDingBats. + * @param int $flags Unsigned 32-bit integer containing flags specifying various characteristics of the font (PDF32000:2008 - 9.8.2 Font Descriptor Flags): +1 for fixed font; +4 for symbol or +32 for non-symbol; +64 for italic. Fixed and Italic mode are generally autodetected so you have to set it to 32 = non-symbolic font (default) or 4 = symbolic font. + * @param string $outpath Output path for generated font files (must be writeable by the web server). Leave empty for default font folder. + * @param int $platid Platform ID for CMAP table to extract (when building a Unicode font for Windows this value should be 3, for Macintosh should be 1). + * @param int $encid Encoding ID for CMAP table to extract (when building a Unicode font for Windows this value should be 1, for Macintosh should be 0). When Platform ID is 3, legal values for Encoding ID are: 0=Symbol, 1=Unicode, 2=ShiftJIS, 3=PRC, 4=Big5, 5=Wansung, 6=Johab, 7=Reserved, 8=Reserved, 9=Reserved, 10=UCS-4. + * @param boolean $addcbbox If true includes the character bounding box information on the php font file. + * @param boolean $link If true link to system font instead of copying the font data (not transportable) - Note: do not work with Type1 fonts. + * @return string|false TCPDF font name or boolean false in case of error. * @author Nicola Asuni * @since 5.9.123 (2010-09-30) * @public static @@ -557,6 +557,7 @@ class TCPDF_FONTS { $numGlyphs = TCPDF_STATIC::_getUSHORT($font, $offset); // ---------- get CIDToGIDMap ---------- $ctg = array(); + $c = 0; foreach ($encodingTables as $enctable) { // get only specified Platform ID and Encoding ID if (($enctable['platformID'] == $platid) AND ($enctable['encodingID'] == $encid)) { @@ -920,8 +921,8 @@ class TCPDF_FONTS { /** * Returs the checksum of a TTF table. - * @param $table (string) table to check - * @param $length (int) length of table in bytes + * @param string $table table to check + * @param int $length length of table in bytes * @return int checksum * @author Nicola Asuni * @since 5.2.000 (2010-06-02) @@ -942,9 +943,9 @@ class TCPDF_FONTS { /** * Returns a subset of the TrueType font data without the unused glyphs. - * @param $font (string) TrueType font data. - * @param $subsetchars (array) Array of used characters (the glyphs to keep). - * @return (string) A subset of TrueType font data without the unused glyphs. + * @param string $font TrueType font data. + * @param array $subsetchars Array of used characters (the glyphs to keep). + * @return string A subset of TrueType font data without the unused glyphs. * @author Nicola Asuni * @since 5.2.000 (2010-06-02) * @public static @@ -956,6 +957,7 @@ class TCPDF_FONTS { // sfnt version must be 0x00010000 for TrueType version 1.0. return $font; } + $c = 0; $offset += 4; // get number of tables $numTables = TCPDF_STATIC::_getUSHORT($font, $offset); @@ -1387,9 +1389,9 @@ class TCPDF_FONTS { /** * Outputs font widths - * @param $font (array) font data - * @param $cidoffset (int) offset for CID values - * @return PDF command string for font widths + * @param array $font font data + * @param int $cidoffset offset for CID values + * @return string PDF command string for font widths * @author Nicola Asuni * @since 4.4.000 (2008-12-07) * @public static @@ -1495,10 +1497,10 @@ class TCPDF_FONTS { /** * Update the CIDToGIDMap string with a new value. - * @param $map (string) CIDToGIDMap. - * @param $cid (int) CID value. - * @param $gid (int) GID value. - * @return (string) CIDToGIDMap. + * @param string $map CIDToGIDMap. + * @param int $cid CID value. + * @param int $gid GID value. + * @return string CIDToGIDMap. * @author Nicola Asuni * @since 5.9.123 (2011-09-29) * @public static @@ -1533,8 +1535,8 @@ class TCPDF_FONTS { /** * Return font full path - * @param $file (string) Font file name. - * @param $fontdir (string) Font directory (set to false fto search on default directories) + * @param string $file Font file name. + * @param string $fontdir Font directory (set to false fto search on default directories) * @return string Font full path or empty string * @author Nicola Asuni * @since 6.0.025 @@ -1558,8 +1560,8 @@ class TCPDF_FONTS { /** * Get a reference font size. - * @param $size (string) String containing font size value. - * @param $refsize (float) Reference font size in points. + * @param string $size String containing font size value. + * @param float $refsize Reference font size in points. * @return float value in points * @public static */ @@ -1657,9 +1659,9 @@ class TCPDF_FONTS { /** * Returns the unicode caracter specified by the value - * @param $c (int) UTF-8 value - * @param $unicode (boolean) True if we are in unicode mode, false otherwise. - * @return Returns the specified character. + * @param int $c UTF-8 value + * @param boolean $unicode True if we are in unicode mode, false otherwise. + * @return string Returns the specified character. * @since 2.3.000 (2008-03-05) * @public static */ @@ -1686,8 +1688,8 @@ class TCPDF_FONTS { /** * Returns the unicode caracter specified by UTF-8 value - * @param $c (int) UTF-8 value - * @return Returns the specified character. + * @param int $c UTF-8 value + * @return string Returns the specified character. * @public static */ public static function unichrUnicode($c) { @@ -1696,8 +1698,8 @@ class TCPDF_FONTS { /** * Returns the unicode caracter specified by ASCII value - * @param $c (int) UTF-8 value - * @return Returns the specified character. + * @param int $c UTF-8 value + * @return string Returns the specified character. * @public static */ public static function unichrASCII($c) { @@ -1734,8 +1736,8 @@ class TCPDF_FONTS { * W1 = 110110yyyyyyyyyy * W2 = 110111xxxxxxxxxx * - * @param $unicode (array) array containing UTF-8 unicode values - * @param $setbom (boolean) if true set the Byte Order Mark (BOM = 0xFEFF) + * @param array $unicode array containing UTF-8 unicode values + * @param boolean $setbom if true set the Byte Order Mark (BOM = 0xFEFF) * @return string * @protected * @author Nicola Asuni @@ -1770,9 +1772,9 @@ class TCPDF_FONTS { /** * Convert an array of UTF8 values to array of unicode characters - * @param $ta (array) The input array of UTF8 values. - * @param $isunicode (boolean) True for Unicode mode, false otherwise. - * @return Return array of unicode characters + * @param array $ta The input array of UTF8 values. + * @param boolean $isunicode True for Unicode mode, false otherwise. + * @return array Return array of unicode characters * @since 4.5.037 (2009-04-07) * @public static */ @@ -1785,11 +1787,11 @@ class TCPDF_FONTS { /** * Extract a slice of the $strarr array and return it as string. - * @param $strarr (string) The input array of characters. - * @param $start (int) the starting element of $strarr. - * @param $end (int) first element that will not be returned. - * @param $unicode (boolean) True if we are in unicode mode, false otherwise. - * @return Return part of a string + * @param string[] $strarr The input array of characters. + * @param int $start the starting element of $strarr. + * @param int $end first element that will not be returned. + * @param boolean $unicode True if we are in unicode mode, false otherwise. + * @return string Return part of a string * @public static */ public static function UTF8ArrSubString($strarr, $start='', $end='', $unicode=true) { @@ -1808,10 +1810,10 @@ class TCPDF_FONTS { /** * Extract a slice of the $uniarr array and return it as string. - * @param $uniarr (string) The input array of characters. - * @param $start (int) the starting element of $strarr. - * @param $end (int) first element that will not be returned. - * @return Return part of a string + * @param string[] $uniarr The input array of characters. + * @param int $start the starting element of $strarr. + * @param int $end first element that will not be returned. + * @return string Return part of a string * @since 4.5.037 (2009-04-07) * @public static */ @@ -1831,7 +1833,7 @@ class TCPDF_FONTS { /** * Converts UTF-8 characters array to array of Latin1 characters array
- * @param $unicode (array) array containing UTF-8 unicode values + * @param array $unicode array containing UTF-8 unicode values * @return array * @author Nicola Asuni * @since 4.8.023 (2010-01-15) @@ -1855,9 +1857,9 @@ class TCPDF_FONTS { } /** - * Converts UTF-8 characters array to array of Latin1 string
- * @param $unicode (array) array containing UTF-8 unicode values - * @return array + * Converts UTF-8 characters array to Latin1 string
+ * @param array $unicode array containing UTF-8 unicode values + * @return string * @author Nicola Asuni * @since 4.8.023 (2010-01-15) * @public static @@ -1882,8 +1884,8 @@ class TCPDF_FONTS { /** * Converts UTF-8 character to integer value.
* Uses the getUniord() method if the value is not cached. - * @param $uch (string) character string to process. - * @return integer Unicode value + * @param string $uch character string to process. + * @return int Unicode value * @public static */ public static function uniord($uch) { @@ -1921,8 +1923,8 @@ class TCPDF_FONTS { * UTF8-tail = %x80-BF * --------------------------------------------------------------------- * - * @param $uch (string) character string to process. - * @return integer Unicode value + * @param string $uch character string to process. + * @return int Unicode value * @author Nicola Asuni * @public static */ @@ -1988,14 +1990,14 @@ class TCPDF_FONTS { /** * Converts UTF-8 strings to codepoints array.
* Invalid byte sequences will be replaced with 0xFFFD (replacement character)
- * @param $str (string) string to process. - * @param $isunicode (boolean) True when the documetn is in Unicode mode, false otherwise. - * @param $currentfont (array) Reference to current font array. + * @param string $str string to process. + * @param boolean $isunicode True when the documetn is in Unicode mode, false otherwise. + * @param array $currentfont Reference to current font array. * @return array containing codepoints (UTF-8 characters values) * @author Nicola Asuni * @public static */ - public static function UTF8StringToArray($str, $isunicode=true, &$currentfont) { + public static function UTF8StringToArray($str, $isunicode, &$currentfont) { if ($isunicode) { // requires PCRE unicode support turned on $chars = TCPDF_STATIC::pregSplit('//','u', $str, -1, PREG_SPLIT_NO_EMPTY); @@ -2014,30 +2016,30 @@ class TCPDF_FONTS { /** * Converts UTF-8 strings to Latin1 when using the standard 14 core fonts.
- * @param $str (string) string to process. - * @param $isunicode (boolean) True when the documetn is in Unicode mode, false otherwise. - * @param $currentfont (array) Reference to current font array. + * @param string $str string to process. + * @param boolean $isunicode True when the documetn is in Unicode mode, false otherwise. + * @param array $currentfont Reference to current font array. * @return string * @since 3.2.000 (2008-06-23) * @public static */ - public static function UTF8ToLatin1($str, $isunicode=true, &$currentfont) { + public static function UTF8ToLatin1($str, $isunicode, &$currentfont) { $unicode = self::UTF8StringToArray($str, $isunicode, $currentfont); // array containing UTF-8 unicode values return self::UTF8ArrToLatin1($unicode); } /** * Converts UTF-8 strings to UTF16-BE.
- * @param $str (string) string to process. - * @param $setbom (boolean) if true set the Byte Order Mark (BOM = 0xFEFF) - * @param $isunicode (boolean) True when the documetn is in Unicode mode, false otherwise. - * @param $currentfont (array) Reference to current font array. + * @param string $str string to process. + * @param boolean $setbom if true set the Byte Order Mark (BOM = 0xFEFF) + * @param boolean $isunicode True when the documetn is in Unicode mode, false otherwise. + * @param array $currentfont Reference to current font array. * @return string * @author Nicola Asuni * @since 1.53.0.TC005 (2005-01-05) * @public static */ - public static function UTF8ToUTF16BE($str, $setbom=false, $isunicode=true, &$currentfont) { + public static function UTF8ToUTF16BE($str, $setbom, $isunicode, &$currentfont) { if (!$isunicode) { return $str; // string is not in unicode } @@ -2047,50 +2049,50 @@ class TCPDF_FONTS { /** * Reverse the RLT substrings using the Bidirectional Algorithm (http://unicode.org/reports/tr9/). - * @param $str (string) string to manipulate. - * @param $setbom (bool) if true set the Byte Order Mark (BOM = 0xFEFF) - * @param $forcertl (bool) if true forces RTL text direction - * @param $isunicode (boolean) True if the document is in Unicode mode, false otherwise. - * @param $currentfont (array) Reference to current font array. + * @param string $str string to manipulate. + * @param bool $setbom if true set the Byte Order Mark (BOM = 0xFEFF) + * @param bool $forcertl if true forces RTL text direction + * @param boolean $isunicode True if the document is in Unicode mode, false otherwise. + * @param array $currentfont Reference to current font array. * @return string * @author Nicola Asuni * @since 2.1.000 (2008-01-08) * @public static */ - public static function utf8StrRev($str, $setbom=false, $forcertl=false, $isunicode=true, &$currentfont) { + public static function utf8StrRev($str, $setbom, $forcertl, $isunicode, &$currentfont) { return self::utf8StrArrRev(self::UTF8StringToArray($str, $isunicode, $currentfont), $str, $setbom, $forcertl, $isunicode, $currentfont); } /** * Reverse the RLT substrings array using the Bidirectional Algorithm (http://unicode.org/reports/tr9/). - * @param $arr (array) array of unicode values. - * @param $str (string) string to manipulate (or empty value). - * @param $setbom (bool) if true set the Byte Order Mark (BOM = 0xFEFF) - * @param $forcertl (bool) if true forces RTL text direction - * @param $isunicode (boolean) True if the document is in Unicode mode, false otherwise. - * @param $currentfont (array) Reference to current font array. + * @param array $arr array of unicode values. + * @param string $str string to manipulate (or empty value). + * @param bool $setbom if true set the Byte Order Mark (BOM = 0xFEFF) + * @param bool $forcertl if true forces RTL text direction + * @param boolean $isunicode True if the document is in Unicode mode, false otherwise. + * @param array $currentfont Reference to current font array. * @return string * @author Nicola Asuni * @since 4.9.000 (2010-03-27) * @public static */ - public static function utf8StrArrRev($arr, $str='', $setbom=false, $forcertl=false, $isunicode=true, &$currentfont) { + public static function utf8StrArrRev($arr, $str, $setbom, $forcertl, $isunicode, &$currentfont) { return self::arrUTF8ToUTF16BE(self::utf8Bidi($arr, $str, $forcertl, $isunicode, $currentfont), $setbom); } /** * Reverse the RLT substrings using the Bidirectional Algorithm (http://unicode.org/reports/tr9/). - * @param $ta (array) array of characters composing the string. - * @param $str (string) string to process - * @param $forcertl (bool) if 'R' forces RTL, if 'L' forces LTR - * @param $isunicode (boolean) True if the document is in Unicode mode, false otherwise. - * @param $currentfont (array) Reference to current font array. + * @param array $ta array of characters composing the string. + * @param string $str string to process + * @param bool $forcertl if 'R' forces RTL, if 'L' forces LTR + * @param boolean $isunicode True if the document is in Unicode mode, false otherwise. + * @param array $currentfont Reference to current font array. * @return array of unicode chars * @author Nicola Asuni * @since 2.4.000 (2008-03-06) * @public static */ - public static function utf8Bidi($ta, $str='', $forcertl=false, $isunicode=true, &$currentfont) { + public static function utf8Bidi($ta, $str, $forcertl, $isunicode, &$currentfont) { // paragraph embedding level $pel = 0; // max level diff --git a/lib/combodo/tcpdf/include/tcpdf_images.php b/lib/combodo/tcpdf/include/tcpdf_images.php index 5e504f210..6f2860c60 100644 --- a/lib/combodo/tcpdf/include/tcpdf_images.php +++ b/lib/combodo/tcpdf/include/tcpdf_images.php @@ -55,6 +55,8 @@ class TCPDF_IMAGES { * Array of hinheritable SVG properties. * @since 5.0.000 (2010-05-02) * @public static + * + * @var string[] */ public static $svginheritprop = array('clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'display', 'fill', 'fill-opacity', 'fill-rule', 'font', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering', 'kerning', 'letter-spacing', 'marker', 'marker-end', 'marker-mid', 'marker-start', 'pointer-events', 'shape-rendering', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-rendering', 'visibility', 'word-spacing', 'writing-mode'); @@ -62,8 +64,8 @@ class TCPDF_IMAGES { /** * Return the image type given the file name or array returned by getimagesize() function. - * @param $imgfile (string) image file name - * @param $iminfo (array) array of image information returned by getimagesize() function. + * @param string $imgfile image file name + * @param array $iminfo array of image information returned by getimagesize() function. * @return string image type * @since 4.8.017 (2009-11-27) * @public static @@ -77,10 +79,7 @@ class TCPDF_IMAGES { } } if (empty($type)) { - $fileinfo = pathinfo($imgfile); - if (isset($fileinfo['extension']) AND (!TCPDF_STATIC::empty_string($fileinfo['extension']))) { - $type = strtolower(trim($fileinfo['extension'])); - } + $type = strtolower(trim(pathinfo(parse_url($imgfile, PHP_URL_PATH), PATHINFO_EXTENSION))); } if ($type == 'jpg') { $type = 'jpeg'; @@ -90,9 +89,9 @@ class TCPDF_IMAGES { /** * Set the transparency for the given GD image. - * @param $new_image (image) GD image object - * @param $image (image) GD image object. - * return GD image object. + * @param resource $new_image GD image object + * @param resource $image GD image object. + * @return resource GD image object $new_image * @since 4.9.016 (2010-04-20) * @public static */ @@ -115,8 +114,8 @@ class TCPDF_IMAGES { /** * Convert the loaded image to a PNG and then return a structure for the PDF creator. * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant. - * @param $image (image) Image object. - * @param $tempfile (string) Temporary file name. + * @param resource $image Image object. + * @param string $tempfile Temporary file name. * return image PNG image object. * @since 4.9.016 (2010-04-20) * @public static @@ -138,10 +137,10 @@ class TCPDF_IMAGES { /** * Convert the loaded image to a JPEG and then return a structure for the PDF creator. * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant. - * @param $image (image) Image object. - * @param $quality (int) JPEG quality. - * @param $tempfile (string) Temporary file name. - * return image JPEG image object. + * @param resource $image Image object. + * @param int $quality JPEG quality. + * @param string $tempfile Temporary file name. + * return array|false image JPEG image object. * @public static */ public static function _toJPEG($image, $quality, $tempfile) { @@ -155,8 +154,8 @@ class TCPDF_IMAGES { /** * Extract info from a JPEG file without using the GD library. - * @param $file (string) image file to parse - * @return array structure containing the image data + * @param string $file image file to parse + * @return array|false structure containing the image data * @public static */ public static function _parsejpeg($file) { @@ -234,8 +233,8 @@ class TCPDF_IMAGES { /** * Extract info from a PNG file without using the GD library. - * @param $file (string) image file to parse - * @return array structure containing the image data + * @param string $file image file to parse + * @return array|false structure containing the image data * @public static */ public static function _parsepng($file) { diff --git a/lib/combodo/tcpdf/include/tcpdf_static.php b/lib/combodo/tcpdf/include/tcpdf_static.php index 06a1dddcc..a118d0588 100644 --- a/lib/combodo/tcpdf/include/tcpdf_static.php +++ b/lib/combodo/tcpdf/include/tcpdf_static.php @@ -7,7 +7,7 @@ // Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com // License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) // ------------------------------------------------------------------- -// Copyright (C) 2002-2015 Nicola Asuni - Tecnick.com LTD +// Copyright (C) 2002-2021 Nicola Asuni - Tecnick.com LTD // // This file is part of TCPDF software library. // @@ -55,7 +55,7 @@ class TCPDF_STATIC { * Current TCPDF version. * @private static */ - private static $tcpdf_version = '6.3.5'; + private static $tcpdf_version = '6.4.4'; /** * String alias for total number of pages. @@ -110,7 +110,7 @@ class TCPDF_STATIC { /** * Return the current TCPDF version. - * @return TCPDF version string + * @return string TCPDF version string * @since 5.9.012 (2010-11-10) * @public static */ @@ -120,7 +120,7 @@ class TCPDF_STATIC { /** * Return the current TCPDF producer. - * @return TCPDF producer string + * @return string TCPDF producer string * @since 6.0.000 (2013-03-16) * @public static */ @@ -130,7 +130,7 @@ class TCPDF_STATIC { /** * Sets the current active configuration setting of magic_quotes_runtime (if the set_magic_quotes_runtime function exist) - * @param $mqr (boolean) FALSE for off, TRUE for on. + * @param boolean $mqr FALSE for off, TRUE for on. * @since 4.6.025 (2009-08-17) * @public static */ @@ -146,7 +146,7 @@ class TCPDF_STATIC { /** * Gets the current active configuration setting of magic_quotes_runtime (if the get_magic_quotes_runtime function exist) - * @return Returns 0 if magic quotes runtime is off or get_magic_quotes_runtime doesn't exist, 1 otherwise. + * @return int Returns 0 if magic quotes runtime is off or get_magic_quotes_runtime doesn't exist, 1 otherwise. * @since 4.6.025 (2009-08-17) * @public static */ @@ -163,13 +163,16 @@ class TCPDF_STATIC { /** * Check if the URL exist. - * @param $url (string) URL to check. - * @return Boolean true if the URl exist, false otherwise. + * @param string $url URL to check. + * @return boolean true if the URl exist, false otherwise. * @since 5.9.204 (2013-01-28) * @public static */ public static function isValidURL($url) { $headers = @get_headers($url); + if ($headers === false) { + return false; + } return (strpos($headers[0], '200') !== false); } @@ -184,8 +187,8 @@ class TCPDF_STATIC { *
  • UTF-8 (hex): 0xC2 0xAD (c2ad)
  • *
  • UTF-8 character: chr(194).chr(173)
  • * - * @param $txt (string) input string - * @param $unicode (boolean) True if we are in unicode mode, false otherwise. + * @param string $txt input string + * @param boolean $unicode True if we are in unicode mode, false otherwise. * @return string without SHY characters. * @since (4.5.019) 2009-02-28 * @public static @@ -201,10 +204,10 @@ class TCPDF_STATIC { /** * Get the border mode accounting for multicell position (opens bottom side of multicell crossing pages) - * @param $brd (mixed) Indicates if borders must be drawn around the cell block. The value can be a number:or a string containing some or all of the following characters (in any order): or an array of line styles for each border group: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param $position (string) multicell position: 'start', 'middle', 'end' - * @param $opencell (boolean) True when the cell is left open at the page bottom, false otherwise. - * @return border mode array + * @param string|array|int $brd Indicates if borders must be drawn around the cell block. The value can be a number:or a string containing some or all of the following characters (in any order): or an array of line styles for each border group: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param string $position multicell position: 'start', 'middle', 'end' + * @param boolean $opencell True when the cell is left open at the page bottom, false otherwise. + * @return array border mode array * @since 4.4.002 (2008-12-09) * @public static */ @@ -275,8 +278,8 @@ class TCPDF_STATIC { /** * Determine whether a string is empty. - * @param $str (string) string to be checked - * @return boolean true if string is empty + * @param string $str string to be checked + * @return bool true if string is empty * @since 4.5.044 (2009-04-16) * @public static */ @@ -286,8 +289,8 @@ class TCPDF_STATIC { /** * Returns a temporary filename for caching object on filesystem. - * @param $type (string) Type of file (name of the subdir on the tcpdf cache folder). - * @param $file_id (string) TCPDF file_id. + * @param string $type Type of file (name of the subdir on the tcpdf cache folder). + * @param string $file_id TCPDF file_id. * @return string filename. * @since 4.5.000 (2008-12-31) * @public static @@ -298,7 +301,7 @@ class TCPDF_STATIC { /** * Add "\" before "\", "(" and ")" - * @param $s (string) string to escape. + * @param string $s string to escape. * @return string escaped string. * @public static */ @@ -309,8 +312,8 @@ class TCPDF_STATIC { /** * Escape some special characters (< > &) for XML output. - * @param $str (string) Input string to convert. - * @return converted string + * @param string $str Input string to convert. + * @return string converted string * @since 5.9.121 (2011-09-28) * @public static */ @@ -322,8 +325,8 @@ class TCPDF_STATIC { /** * Creates a copy of a class object - * @param $object (object) class object to be cloned - * @return cloned object + * @param object $object class object to be cloned + * @return object cloned object * @since 4.5.029 (2009-03-19) * @public static */ @@ -337,8 +340,8 @@ class TCPDF_STATIC { /** * Output input data and compress it if possible. - * @param $data (string) Data to output. - * @param $length (int) Data length in bytes. + * @param string $data Data to output. + * @param int $length Data length in bytes. * @since 5.9.086 * @public static */ @@ -352,10 +355,10 @@ class TCPDF_STATIC { /** * Replace page number aliases with number. - * @param $page (string) Page content. - * @param $replace (array) Array of replacements (array keys are replacement strings, values are alias arrays). - * @param $diff (int) If passed, this will be set to the total char number difference between alias and replacements. - * @return replaced page content and updated $diff parameter as array. + * @param string $page Page content. + * @param array $replace Array of replacements (array keys are replacement strings, values are alias arrays). + * @param int $diff If passed, this will be set to the total char number difference between alias and replacements. + * @return array replaced page content and updated $diff parameter as array. * @public static */ public static function replacePageNumAliases($page, $replace, $diff=0) { @@ -372,7 +375,7 @@ class TCPDF_STATIC { /** * Returns timestamp in seconds from formatted date-time. - * @param $date (string) Formatted date-time. + * @param string $date Formatted date-time. * @return int seconds. * @since 5.9.152 (2012-03-23) * @public static @@ -387,7 +390,7 @@ class TCPDF_STATIC { /** * Returns a formatted date-time. - * @param $time (int) Time in seconds. + * @param int $time Time in seconds. * @return string escaped date string. * @since 5.9.152 (2012-03-23) * @public static @@ -398,7 +401,7 @@ class TCPDF_STATIC { /** * Returns a string containing random data to be used as a seed for encryption methods. - * @param $seed (string) starting seed value + * @param string $seed starting seed value * @return string containing random data * @author Nicola Asuni * @since 5.9.006 (2010-10-19) @@ -422,8 +425,8 @@ class TCPDF_STATIC { /** * Encrypts a string using MD5 and returns it's value as a binary string. - * @param $str (string) input string - * @return String MD5 encrypted binary string + * @param string $str input string + * @return string MD5 encrypted binary string * @since 2.0.000 (2008-01-02) * @public static */ @@ -432,11 +435,11 @@ class TCPDF_STATIC { } /** - * Returns the input text exrypted using AES algorithm and the specified key. + * Returns the input text encrypted using AES algorithm and the specified key. * This method requires openssl or mcrypt. Text is padded to 16bytes blocks - * @param $key (string) encryption key - * @param $text (String) input text to be encrypted - * @return String encrypted text + * @param string $key encryption key + * @param string $text input text to be encrypted + * @return string encrypted text * @author Nicola Asuni * @since 5.0.005 (2010-05-11) * @public static @@ -446,8 +449,12 @@ class TCPDF_STATIC { $padding = 16 - (strlen($text) % 16); $text .= str_repeat(chr($padding), $padding); if (extension_loaded('openssl')) { - $iv = openssl_random_pseudo_bytes (openssl_cipher_iv_length('aes-256-cbc')); - $text = openssl_encrypt($text, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); + $algo = 'aes-256-cbc'; + if (strlen($key) == 16) { + $algo = 'aes-128-cbc'; + } + $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($algo)); + $text = openssl_encrypt($text, $algo, $key, OPENSSL_RAW_DATA, $iv); return $iv.substr($text, 0, -16); } $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND); @@ -457,19 +464,23 @@ class TCPDF_STATIC { } /** - * Returns the input text exrypted using AES algorithm and the specified key. + * Returns the input text encrypted using AES algorithm and the specified key. * This method requires openssl or mcrypt. Text is not padded - * @param $key (string) encryption key - * @param $text (String) input text to be encrypted - * @return String encrypted text + * @param string $key encryption key + * @param string $text input text to be encrypted + * @return string encrypted text * @author Nicola Asuni * @since TODO * @public static */ public static function _AESnopad($key, $text) { if (extension_loaded('openssl')) { - $iv = str_repeat("\x00", openssl_cipher_iv_length('aes-256-cbc')); - $text = openssl_encrypt($text, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); + $algo = 'aes-256-cbc'; + if (strlen($key) == 16) { + $algo = 'aes-128-cbc'; + } + $iv = str_repeat("\x00", openssl_cipher_iv_length($algo)); + $text = openssl_encrypt($text, $algo, $key, OPENSSL_RAW_DATA, $iv); return substr($text, 0, -16); } $iv = str_repeat("\x00", mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)); @@ -480,11 +491,11 @@ class TCPDF_STATIC { /** * Returns the input text encrypted using RC4 algorithm and the specified key. * RC4 is the standard encryption algorithm used in PDF format - * @param $key (string) Encryption key. - * @param $text (String) Input text to be encrypted. - * @param $last_enc_key (String) Reference to last RC4 key encrypted. - * @param $last_enc_key_c (String) Reference to last RC4 computed key. - * @return String encrypted text + * @param string $key Encryption key. + * @param string $text Input text to be encrypted. + * @param string $last_enc_key Reference to last RC4 key encrypted. + * @param string $last_enc_key_c Reference to last RC4 computed key. + * @return string encrypted text * @since 2.0.000 (2008-01-02) * @author Klemen Vodopivec, Nicola Asuni * @public static @@ -495,7 +506,7 @@ class TCPDF_STATIC { return $out; } if ($last_enc_key != $key) { - $k = str_repeat($key, ((256 / strlen($key)) + 1)); + $k = str_repeat($key, (int) ((256 / strlen($key)) + 1)); $rc4 = range(0, 255); $j = 0; for ($i = 0; $i < 256; ++$i) { @@ -527,8 +538,8 @@ class TCPDF_STATIC { /** * Return the permission code used on encryption (P value). - * @param $permissions (Array) the set of permissions (specify the ones you want to block). - * @param $mode (int) encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit. + * @param array $permissions the set of permissions (specify the ones you want to block). + * @param int $mode encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit. * @since 5.0.005 (2010-05-12) * @author Nicola Asuni * @public static @@ -564,8 +575,8 @@ class TCPDF_STATIC { /** * Convert hexadecimal string to string - * @param $bs (string) byte-string to convert - * @return String + * @param string $bs byte-string to convert + * @return string * @since 5.0.005 (2010-05-12) * @author Nicola Asuni * @public static @@ -586,8 +597,8 @@ class TCPDF_STATIC { /** * Convert string to hexadecimal string (byte string) - * @param $s (string) string to convert - * @return byte string + * @param string $s string to convert + * @return string byte string * @since 5.0.010 (2010-05-17) * @author Nicola Asuni * @public static @@ -603,8 +614,8 @@ class TCPDF_STATIC { /** * Convert encryption P value to a string of bytes, low-order byte first. - * @param $protection (string) 32bit encryption permission value (P value) - * @return String + * @param string $protection 32bit encryption permission value (P value) + * @return string * @since 5.0.005 (2010-05-12) * @author Nicola Asuni * @public static @@ -620,8 +631,8 @@ class TCPDF_STATIC { /** * Encode a name object. - * @param $name (string) Name object to encode. - * @return (string) Encoded name object. + * @param string $name Name object to encode. + * @return string Encoded name object. * @author Nicola Asuni * @since 5.9.097 (2011-06-23) * @public static @@ -642,9 +653,9 @@ class TCPDF_STATIC { /** * Convert JavaScript form fields properties array to Annotation Properties array. - * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param $spot_colors (array) Reference to spot colors array. - * @param $rtl (boolean) True if in Right-To-Left text direction mode, false otherwise. + * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. + * @param array $spot_colors Reference to spot colors array. + * @param boolean $rtl True if in Right-To-Left text direction mode, false otherwise. * @return array of annotation properties * @author Nicola Asuni * @since 4.8.000 (2009-09-06) @@ -652,7 +663,7 @@ class TCPDF_STATIC { */ public static function getAnnotOptFromJSProp($prop, &$spot_colors, $rtl=false) { if (isset($prop['aopt']) AND is_array($prop['aopt'])) { - // the annotation options area lready defined + // the annotation options are already defined return $prop['aopt']; } $opt = array(); // value to be returned @@ -1011,8 +1022,9 @@ class TCPDF_STATIC { /** * Format the page numbers. - * This method can be overriden for custom formats. - * @param $num (int) page number + * This method can be overridden for custom formats. + * @param int $num page number + * @return string * @since 4.2.005 (2008-11-06) * @public static */ @@ -1022,8 +1034,9 @@ class TCPDF_STATIC { /** * Format the page numbers on the Table Of Content. - * This method can be overriden for custom formats. - * @param $num (int) page number + * This method can be overridden for custom formats. + * @param int $num page number + * @return string * @since 4.5.001 (2009-01-04) * @see addTOC(), addHTMLTOC() * @public static @@ -1034,8 +1047,8 @@ class TCPDF_STATIC { /** * Extracts the CSS properties from a CSS string. - * @param $cssdata (string) string containing CSS definitions. - * @return An array where the keys are the CSS selectors and the values are the CSS properties. + * @param string $cssdata string containing CSS definitions. + * @return array An array where the keys are the CSS selectors and the values are the CSS properties. * @author Nicola Asuni * @since 5.1.000 (2010-05-25) * @public static @@ -1125,20 +1138,20 @@ class TCPDF_STATIC { /** * Cleanup HTML code (requires HTML Tidy library). - * @param $html (string) htmlcode to fix - * @param $default_css (string) CSS commands to add - * @param $tagvs (array) parameters for setHtmlVSpace method - * @param $tidy_options (array) options for tidy_parse_string function - * @param $tagvspaces (array) Array of vertical spaces for tags. + * @param string $html htmlcode to fix + * @param string $default_css CSS commands to add + * @param array|null $tagvs parameters for setHtmlVSpace method + * @param array|null $tidy_options options for tidy_parse_string function + * @param array $tagvspaces Array of vertical spaces for tags. * @return string XHTML code cleaned up * @author Nicola Asuni * @since 5.9.017 (2010-11-16) * @see setHtmlVSpace() * @public static */ - public static function fixHTMLCode($html, $default_css='', $tagvs='', $tidy_options='', &$tagvspaces) { + public static function fixHTMLCode($html, $default_css, $tagvs, $tidy_options, &$tagvspaces) { // configure parameters for HTML Tidy - if ($tidy_options === '') { + if (TCPDF_STATIC::empty_string($tidy_options)) { $tidy_options = array ( 'clean' => 1, 'drop-empty-paras' => 0, @@ -1185,7 +1198,7 @@ class TCPDF_STATIC { // remove some empty tag blocks $html = preg_replace('/]*)><\/div>/', '', $html); $html = preg_replace('/]*)><\/p>/', '', $html); - if ($tagvs !== '') { + if (!TCPDF_STATIC::empty_string($tagvs)) { // set vertical space for some XHTML tags $tagvspaces = $tagvs; } @@ -1195,9 +1208,9 @@ class TCPDF_STATIC { /** * Returns true if the CSS selector is valid for the selected HTML tag - * @param $dom (array) array of HTML tags and properties - * @param $key (int) key of the current HTML tag - * @param $selector (string) CSS selector string + * @param array $dom array of HTML tags and properties + * @param int $key key of the current HTML tag + * @param string $selector CSS selector string * @return true if the selector is valid, false otherwise * @since 5.1.000 (2010-05-25) * @public static @@ -1355,9 +1368,9 @@ class TCPDF_STATIC { /** * Returns the styles array that apply for the selected HTML tag. - * @param $dom (array) array of HTML tags and properties - * @param $key (int) key of the current HTML tag - * @param $css (array) array of CSS properties + * @param array $dom array of HTML tags and properties + * @param int $key key of the current HTML tag + * @param array $css array of CSS properties * @return array containing CSS properties * @since 5.1.000 (2010-05-25) * @public static @@ -1402,7 +1415,7 @@ class TCPDF_STATIC { /** * Compact CSS data array into single string. - * @param $css (array) array of CSS properties + * @param array $css array of CSS properties * @return string containing merged CSS properties * @since 5.9.070 (2011-04-19) * @public static @@ -1433,13 +1446,17 @@ class TCPDF_STATIC { /** * Returns the Roman representation of an integer number - * @param $number (int) number to convert + * @param int $number number to convert * @return string roman representation of the specified number * @since 4.4.004 (2008-12-10) * @public static */ public static function intToRoman($number) { $roman = ''; + if ($number >= 4000) { + // do not represent numbers above 4000 in Roman numerals + return strval($number); + } while ($number >= 1000) { $roman .= 'M'; $number -= 1000; @@ -1497,10 +1514,10 @@ class TCPDF_STATIC { /** * Find position of last occurrence of a substring in a string - * @param $haystack (string) The string to search in. - * @param $needle (string) substring to search. - * @param $offset (int) May be specified to begin searching an arbitrary number of characters into the string. - * @return Returns the position where the needle exists. Returns FALSE if the needle was not found. + * @param string $haystack The string to search in. + * @param string $needle substring to search. + * @param int $offset May be specified to begin searching an arbitrary number of characters into the string. + * @return int|false Returns the position where the needle exists. Returns FALSE if the needle was not found. * @since 4.8.038 (2010-03-13) * @public static */ @@ -1513,7 +1530,7 @@ class TCPDF_STATIC { /** * Returns an array of hyphenation patterns. - * @param $file (string) TEX file containing hypenation patterns. TEX pattrns can be downloaded from http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ + * @param string $file TEX file containing hypenation patterns. TEX patterns can be downloaded from http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ * @return array of hyphenation patterns * @author Nicola Asuni * @since 4.9.012 (2010-04-12) @@ -1546,7 +1563,7 @@ class TCPDF_STATIC { /** * Get the Path-Painting Operators. - * @param $style (string) Style of rendering. Possible values are: + * @param string $style Style of rendering. Possible values are: *
      *
    • S or D: Stroke the path.
    • *
    • s or d: Close and stroke the path.
    • @@ -1560,7 +1577,8 @@ class TCPDF_STATIC { *
    • CEO: Clipping mode using the nonzero winding number rule to determine which regions lie inside the clipping path
    • *
    • n: End the path object without filling or stroking it.
    • *
    - * @param $default (string) default style + * @param string $default default style + * @return string * @author Nicola Asuni * @since 5.0.000 (2010-04-30) * @public static @@ -1637,9 +1655,9 @@ class TCPDF_STATIC { /** * Get the product of two SVG tranformation matrices - * @param $ta (array) first SVG tranformation matrix - * @param $tb (array) second SVG tranformation matrix - * @return transformation array + * @param array $ta first SVG tranformation matrix + * @param array $tb second SVG tranformation matrix + * @return array transformation array * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @public static @@ -1657,7 +1675,7 @@ class TCPDF_STATIC { /** * Get the tranformation matrix from SVG transform attribute - * @param $attribute (string) transformation + * @param string $attribute transformation * @return array of transformations * @author Nicola Asuni * @since 5.0.000 (2010-05-02) @@ -1752,10 +1770,10 @@ class TCPDF_STATIC { /** * Returns the angle in radiants between two vectors - * @param $x1 (int) X coordinate of first vector point - * @param $y1 (int) Y coordinate of first vector point - * @param $x2 (int) X coordinate of second vector point - * @param $y2 (int) Y coordinate of second vector point + * @param int $x1 X coordinate of first vector point + * @param int $y1 Y coordinate of first vector point + * @param int $x2 X coordinate of second vector point + * @param int $y2 Y coordinate of second vector point * @author Nicola Asuni * @since 5.0.000 (2010-05-04) * @public static @@ -1777,17 +1795,20 @@ class TCPDF_STATIC { /** * Split string by a regular expression. * This is a wrapper for the preg_split function to avoid the bug: https://bugs.php.net/bug.php?id=45850 - * @param $pattern (string) The regular expression pattern to search for without the modifiers, as a string. - * @param $modifiers (string) The modifiers part of the pattern, - * @param $subject (string) The input string. - * @param $limit (int) If specified, then only substrings up to limit are returned with the rest of the string being placed in the last substring. A limit of -1, 0 or NULL means "no limit" and, as is standard across PHP, you can use NULL to skip to the flags parameter. - * @param $flags (int) The flags as specified on the preg_split PHP function. - * @return Returns an array containing substrings of subject split along boundaries matched by pattern.modifier + * @param string $pattern The regular expression pattern to search for without the modifiers, as a string. + * @param string $modifiers The modifiers part of the pattern, + * @param string $subject The input string. + * @param int $limit If specified, then only substrings up to limit are returned with the rest of the string being placed in the last substring. A limit of -1, 0 or NULL means "no limit" and, as is standard across PHP, you can use NULL to skip to the flags parameter. + * @param int $flags The flags as specified on the preg_split PHP function. + * @return array Returns an array containing substrings of subject split along boundaries matched by pattern.modifier * @author Nicola Asuni * @since 6.0.023 * @public static */ public static function pregSplit($pattern, $modifiers, $subject, $limit=NULL, $flags=NULL) { + // PHP 8.1 deprecates nulls for $limit and $flags + $limit = $limit === null ? -1 : $limit; + $flags = $flags === null ? 0 : $flags; // the bug only happens on PHP 5.2 when using the u modifier if ((strpos($modifiers, 'u') === FALSE) OR (count(preg_split('//u', "\n\t", -1, PREG_SPLIT_NO_EMPTY)) == 2)) { return preg_split($pattern.$modifiers, $subject, $limit, $flags); @@ -1807,9 +1828,9 @@ class TCPDF_STATIC { /** * Wrapper to use fopen only with local files - * @param filename (string) Name of the file to open - * @param $mode (string) - * @return Returns a file pointer resource on success, or FALSE on error. + * @param string $filename Name of the file to open + * @param string $mode + * @return resource|false Returns a file pointer resource on success, or FALSE on error. * @public static */ public static function fopenLocal($filename, $mode) { @@ -1823,9 +1844,10 @@ class TCPDF_STATIC { /** * Check if the URL exist. - * @param url (string) URL to check. - * @return Returns TRUE if the URL exists; FALSE otherwise. + * @param string $url URL to check. + * @return bool Returns TRUE if the URL exists; FALSE otherwise. * @public static + * @since 6.2.25 */ public static function url_exists($url) { $crs = curl_init(); @@ -1842,6 +1864,10 @@ class TCPDF_STATIC { curl_setopt($crs, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($crs, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($crs, CURLOPT_USERAGENT, 'tc-lib-file'); + curl_setopt($crs, CURLOPT_MAXREDIRS, 5); + if (defined('CURLOPT_PROTOCOLS')) { + curl_setopt($crs, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS | CURLPROTO_HTTP | CURLPROTO_FTP | CURLPROTO_FTPS); + } curl_exec($crs); $code = curl_getinfo($crs, CURLINFO_HTTP_CODE); curl_close($crs); @@ -1872,8 +1898,8 @@ class TCPDF_STATIC { * Wrapper for file_exists. * Checks whether a file or directory exists. * Only allows some protocols and local files. - * @param filename (string) Path to the file or directory. - * @return Returns TRUE if the file or directory specified by filename exists; FALSE otherwise. + * @param string $filename Path to the file or directory. + * @return bool Returns TRUE if the file or directory specified by filename exists; FALSE otherwise. * @public static */ public static function file_exists($filename) { @@ -1889,8 +1915,8 @@ class TCPDF_STATIC { /** * Reads entire file into a string. * The file can be also an URL. - * @param $file (string) Name of the file or URL to read. - * @return The function returns the read data or FALSE on failure. + * @param string $file Name of the file or URL to read. + * @return string|false The function returns the read data or FALSE on failure. * @author Nicola Asuni * @since 6.0.025 * @public static @@ -1973,6 +1999,10 @@ class TCPDF_STATIC { curl_setopt($crs, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($crs, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($crs, CURLOPT_USERAGENT, 'tc-lib-file'); + curl_setopt($crs, CURLOPT_MAXREDIRS, 5); + if (defined('CURLOPT_PROTOCOLS')) { + curl_setopt($crs, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS | CURLPROTO_HTTP | CURLPROTO_FTP | CURLPROTO_FTPS); + } $ret = curl_exec($crs); curl_close($crs); if ($ret !== false) { @@ -1985,8 +2015,8 @@ class TCPDF_STATIC { /** * Get ULONG from string (Big Endian 32-bit unsigned integer). - * @param $str (string) string from where to extract value - * @param $offset (int) point from where to read the data + * @param string $str string from where to extract value + * @param int $offset point from where to read the data * @return int 32 bit value * @author Nicola Asuni * @since 5.2.000 (2010-06-02) @@ -1999,8 +2029,8 @@ class TCPDF_STATIC { /** * Get USHORT from string (Big Endian 16-bit unsigned integer). - * @param $str (string) string from where to extract value - * @param $offset (int) point from where to read the data + * @param string $str string from where to extract value + * @param int $offset point from where to read the data * @return int 16 bit value * @author Nicola Asuni * @since 5.2.000 (2010-06-02) @@ -2013,8 +2043,8 @@ class TCPDF_STATIC { /** * Get SHORT from string (Big Endian 16-bit signed integer). - * @param $str (string) String from where to extract value. - * @param $offset (int) Point from where to read the data. + * @param string $str String from where to extract value. + * @param int $offset Point from where to read the data. * @return int 16 bit value * @author Nicola Asuni * @since 5.2.000 (2010-06-02) @@ -2027,8 +2057,8 @@ class TCPDF_STATIC { /** * Get FWORD from string (Big Endian 16-bit signed integer). - * @param $str (string) String from where to extract value. - * @param $offset (int) Point from where to read the data. + * @param string $str String from where to extract value. + * @param int $offset Point from where to read the data. * @return int 16 bit value * @author Nicola Asuni * @since 5.9.123 (2011-09-30) @@ -2044,8 +2074,8 @@ class TCPDF_STATIC { /** * Get UFWORD from string (Big Endian 16-bit unsigned integer). - * @param $str (string) string from where to extract value - * @param $offset (int) point from where to read the data + * @param string $str string from where to extract value + * @param int $offset point from where to read the data * @return int 16 bit value * @author Nicola Asuni * @since 5.9.123 (2011-09-30) @@ -2058,8 +2088,8 @@ class TCPDF_STATIC { /** * Get FIXED from string (32-bit signed fixed-point number (16.16). - * @param $str (string) string from where to extract value - * @param $offset (int) point from where to read the data + * @param string $str string from where to extract value + * @param int $offset point from where to read the data * @return int 16 bit value * @author Nicola Asuni * @since 5.9.123 (2011-09-30) @@ -2076,8 +2106,8 @@ class TCPDF_STATIC { /** * Get BYTE from string (8-bit unsigned integer). - * @param $str (string) String from where to extract value. - * @param $offset (int) Point from where to read the data. + * @param string $str String from where to extract value. + * @param int $offset Point from where to read the data. * @return int 8 bit value * @author Nicola Asuni * @since 5.2.000 (2010-06-02) @@ -2090,9 +2120,9 @@ class TCPDF_STATIC { /** * Binary-safe and URL-safe file read. * Reads up to length bytes from the file pointer referenced by handle. Reading stops as soon as one of the following conditions is met: length bytes have been read; EOF (end of file) is reached. - * @param $handle (resource) - * @param $length (int) - * @return Returns the read string or FALSE in case of error. + * @param resource $handle + * @param int $length + * @return string|false Returns the read string or FALSE in case of error. * @author Nicola Asuni * @since 4.5.027 (2009-03-16) * @public static @@ -2111,8 +2141,8 @@ class TCPDF_STATIC { /** * Read a 4-byte (32 bit) integer from file. - * @param $f (string) file name. - * @return 4-byte integer + * @param resource $f file resource. + * @return int 4-byte integer * @public static */ public static function _freadint($f) { @@ -2120,11 +2150,12 @@ class TCPDF_STATIC { return $a['i']; } - /** * Array of page formats * measures are calculated in this way: (inches * 72) or (millimeters * 72 / 25.4) * @public static + * + * @var array */ public static $page_formats = array( // ISO 216 A Series + 2 SIS 014711 extensions @@ -2480,7 +2511,7 @@ class TCPDF_STATIC { /** * Get page dimensions from format name. - * @param $format (mixed) The format name @see self::$page_format
      + * @param mixed $format The format name @see self::$page_format
        * @return array containing page width and height in points * @since 5.0.010 (2010-05-17) * @public static @@ -2494,20 +2525,20 @@ class TCPDF_STATIC { /** * Set page boundaries. - * @param $page (int) page number - * @param $type (string) valid values are:
        • 'MediaBox' : the boundaries of the physical medium on which the page shall be displayed or printed;
        • 'CropBox' : the visible region of default user space;
        • 'BleedBox' : the region to which the contents of the page shall be clipped when output in a production environment;
        • 'TrimBox' : the intended dimensions of the finished page after trimming;
        • 'ArtBox' : the page's meaningful content (including potential white space).
        - * @param $llx (float) lower-left x coordinate in user units. - * @param $lly (float) lower-left y coordinate in user units. - * @param $urx (float) upper-right x coordinate in user units. - * @param $ury (float) upper-right y coordinate in user units. - * @param $points (boolean) If true uses user units as unit of measure, otherwise uses PDF points. - * @param $k (float) Scale factor (number of points in user unit). - * @param $pagedim (array) Array of page dimensions. - * @return pagedim array of page dimensions. + * @param int $page page number + * @param string $type valid values are:
        • 'MediaBox' : the boundaries of the physical medium on which the page shall be displayed or printed;
        • 'CropBox' : the visible region of default user space;
        • 'BleedBox' : the region to which the contents of the page shall be clipped when output in a production environment;
        • 'TrimBox' : the intended dimensions of the finished page after trimming;
        • 'ArtBox' : the page's meaningful content (including potential white space).
        + * @param float $llx lower-left x coordinate in user units. + * @param float $lly lower-left y coordinate in user units. + * @param float $urx upper-right x coordinate in user units. + * @param float $ury upper-right y coordinate in user units. + * @param boolean $points If true uses user units as unit of measure, otherwise uses PDF points. + * @param float $k Scale factor (number of points in user unit). + * @param array $pagedim Array of page dimensions. + * @return array pagedim array of page dimensions. * @since 5.0.010 (2010-05-17) * @public static */ - public static function setPageBoxes($page, $type, $llx, $lly, $urx, $ury, $points=false, $k, $pagedim=array()) { + public static function setPageBoxes($page, $type, $llx, $lly, $urx, $ury, $points, $k, $pagedim=array()) { if (!isset($pagedim[$page])) { // initialize array $pagedim[$page] = array(); @@ -2527,9 +2558,9 @@ class TCPDF_STATIC { /** * Swap X and Y coordinates of page boxes (change page boxes orientation). - * @param $page (int) page number - * @param $pagedim (array) Array of page dimensions. - * @return pagedim array of page dimensions. + * @param int $page page number + * @param array $pagedim Array of page dimensions. + * @return array pagedim array of page dimensions. * @since 5.0.010 (2010-05-17) * @public static */ @@ -2550,8 +2581,8 @@ class TCPDF_STATIC { /** * Get the canonical page layout mode. - * @param $layout (string) The page layout. Possible values are:
        • SinglePage Display one page at a time
        • OneColumn Display the pages in one column
        • TwoColumnLeft Display the pages in two columns, with odd-numbered pages on the left
        • TwoColumnRight Display the pages in two columns, with odd-numbered pages on the right
        • TwoPageLeft (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left
        • TwoPageRight (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right
        - * @return (string) Canonical page layout name. + * @param string $layout The page layout. Possible values are:
        • SinglePage Display one page at a time
        • OneColumn Display the pages in one column
        • TwoColumnLeft Display the pages in two columns, with odd-numbered pages on the left
        • TwoColumnRight Display the pages in two columns, with odd-numbered pages on the right
        • TwoPageLeft (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left
        • TwoPageRight (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right
        + * @return string Canonical page layout name. * @public static */ public static function getPageLayoutMode($layout='SinglePage') { @@ -2593,8 +2624,8 @@ class TCPDF_STATIC { /** * Get the canonical page layout mode. - * @param $mode (string) A name object specifying how the document should be displayed when opened:
        • UseNone Neither document outline nor thumbnail images visible
        • UseOutlines Document outline visible
        • UseThumbs Thumbnail images visible
        • FullScreen Full-screen mode, with no menu bar, window controls, or any other window visible
        • UseOC (PDF 1.5) Optional content group panel visible
        • UseAttachments (PDF 1.6) Attachments panel visible
        - * @return (string) Canonical page mode name. + * @param string $mode A name object specifying how the document should be displayed when opened:
        • UseNone Neither document outline nor thumbnail images visible
        • UseOutlines Document outline visible
        • UseThumbs Thumbnail images visible
        • FullScreen Full-screen mode, with no menu bar, window controls, or any other window visible
        • UseOC (PDF 1.5) Optional content group panel visible
        • UseAttachments (PDF 1.6) Attachments panel visible
        + * @return string Canonical page mode name. * @public static */ public static function getPageMode($mode='UseNone') { diff --git a/lib/combodo/tcpdf/tcpdf.php b/lib/combodo/tcpdf/tcpdf.php index a71afc3a8..400434730 100644 --- a/lib/combodo/tcpdf/tcpdf.php +++ b/lib/combodo/tcpdf/tcpdf.php @@ -1,13 +1,13 @@ + * @phpstan-var array{0: string, 1: string, 2: float|null} */ protected $header_font; /** * Default font used on page footer. * @protected + * @var array + * @phpstan-var array{0: string, 1: string, 2: float|null} */ protected $footer_font; @@ -652,7 +656,7 @@ class TCPDF { protected $header_title = ''; /** - * String to pring on page header after title. + * String to print on page header after title. * @protected */ protected $header_string = ''; @@ -661,6 +665,8 @@ class TCPDF { * Color for header text (RGB array). * @since 5.9.174 (2012-07-25) * @protected + * @var int[] + * @phpstan-var array{0: int, 1: int, 2: int} */ protected $header_text_color = array(0,0,0); @@ -668,6 +674,8 @@ class TCPDF { * Color for header line (RGB array). * @since 5.9.174 (2012-07-25) * @protected + * @var int[] + * @phpstan-var array{0: int, 1: int, 2: int} */ protected $header_line_color = array(0,0,0); @@ -675,6 +683,8 @@ class TCPDF { * Color for footer text (RGB array). * @since 5.9.174 (2012-07-25) * @protected + * @var int[] + * @phpstan-var array{0: int, 1: int, 2: int} */ protected $footer_text_color = array(0,0,0); @@ -682,6 +692,8 @@ class TCPDF { * Color for footer line (RGB array). * @since 5.9.174 (2012-07-25) * @protected + * @var int[] + * @phpstan-var array{0: int, 1: int, 2: int} */ protected $footer_line_color = array(0,0,0); @@ -773,13 +785,6 @@ class TCPDF { */ protected $encoding = 'UTF-8'; - /** - * PHP internal encoding. - * @protected - * @since 1.53.0.TC016 - */ - protected $internal_encoding; - /** * Boolean flag to indicate if the document language is Right-To-Left. * @protected @@ -923,6 +928,7 @@ class TCPDF { * Default cell height ratio. * @protected * @since 3.0.014 (2008-05-23) + * @var float */ protected $cell_height_ratio = K_CELL_HEIGHT_RATIO; @@ -1800,6 +1806,7 @@ class TCPDF { * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008). * @protected * @since 5.9.152 (2012-03-23) + * @var array */ protected $overprint = array('OP' => false, 'op' => false, 'OPM' => 0); @@ -1832,6 +1839,23 @@ class TCPDF { */ protected $gdgammacache = array(); + /** + * Cache array for file content + * @protected + * @var array + * @since 6.3.5 (2020-09-28) + */ + protected $fileContentCache = array(); + + /** + * Whether to allow local file path in image html tags, when prefixed with file:// + * + * @var bool + * @protected + * @since 6.4 (2020-07-23) + */ + protected $allowLocalFiles = false; + //------------------------------------------------------------ // METHODS //------------------------------------------------------------ @@ -1840,24 +1864,17 @@ class TCPDF { * This is the class constructor. * It allows to set up the page format, the orientation and the measure unit used in all the methods (except for the font sizes). * - * IMPORTANT: Please note that this method sets the mb_internal_encoding to ASCII, so if you are using the mbstring module functions with TCPDF you need to correctly set/unset the mb_internal_encoding when needed. - * - * @param $orientation (string) page orientation. Possible values are (case insensitive):
        • P or Portrait (default)
        • L or Landscape
        • '' (empty string) for automatic orientation
        - * @param $unit (string) User measure unit. Possible values are:
        • pt: point
        • mm: millimeter (default)
        • cm: centimeter
        • in: inch

        A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit. - * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). - * @param $unicode (boolean) TRUE means that the input text is unicode (default = true) - * @param $encoding (string) Charset encoding (used only when converting back html entities); default is UTF-8. - * @param $diskcache (boolean) DEPRECATED FEATURE - * @param $pdfa (integer) If not false, set the document to PDF/A mode and the good version (1 or 3). + * @param string $orientation page orientation. Possible values are (case insensitive):
        • P or Portrait (default)
        • L or Landscape
        • '' (empty string) for automatic orientation
        + * @param string $unit User measure unit. Possible values are:
        • pt: point
        • mm: millimeter (default)
        • cm: centimeter
        • in: inch

        A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit. + * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). + * @param boolean $unicode TRUE means that the input text is unicode (default = true) + * @param string $encoding Charset encoding (used only when converting back html entities); default is UTF-8. + * @param boolean $diskcache DEPRECATED FEATURE + * @param false|integer $pdfa If not false, set the document to PDF/A mode and the good version (1 or 3). * @public * @see getPageSizeFromFormat(), setPageFormat() */ public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) { - /* Set internal character encoding to ASCII */ - if (function_exists('mb_internal_encoding') AND mb_internal_encoding()) { - $this->internal_encoding = mb_internal_encoding(); - mb_internal_encoding('ASCII'); - } // set file ID for trailer $serformat = (is_array($format) ? json_encode($format) : $format); $this->file_id = md5(TCPDF_STATIC::getRandomSeed('TCPDF'.$orientation.$unit.$serformat.$encoding)); @@ -1932,7 +1949,7 @@ class TCPDF { $this->setPageFormat($format, $orientation); // page margins (1 cm) $margin = 28.35 / $this->k; - $this->SetMargins($margin, $margin); + $this->setMargins($margin, $margin); $this->clMargin = $this->lMargin; $this->crMargin = $this->rMargin; // internal cell padding @@ -1947,11 +1964,11 @@ class TCPDF { $this->linestyleJoin = '0 j'; $this->linestyleDash = '[] 0 d'; // automatic page break - $this->SetAutoPageBreak(true, (2 * $margin)); + $this->setAutoPageBreak(true, (2 * $margin)); // full width display mode - $this->SetDisplayMode('fullwidth'); + $this->setDisplayMode('fullwidth'); // compression - $this->SetCompression(); + $this->setCompression(); // set default PDF version number $this->setPDFVersion(); $this->tcpdflink = true; @@ -1982,7 +1999,7 @@ class TCPDF { // initialize some settings TCPDF_FONTS::utf8Bidi(array(), '', false, $this->isunicode, $this->CurrentFont); // set default font - $this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt); + $this->setFont($this->FontFamily, $this->FontStyle, $this->FontSizePt); $this->setHeaderFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt)); $this->setFooterFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt)); // check if PCRE Unicode support is enabled @@ -2024,7 +2041,7 @@ class TCPDF { /** * Set the units of measure for the document. - * @param $unit (string) User measure unit. Possible values are:
        • pt: point
        • mm: millimeter (default)
        • cm: centimeter
        • in: inch

        A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit. + * @param string $unit User measure unit. Possible values are:
        • pt: point
        • mm: millimeter (default)
        • cm: centimeter
        • in: inch

        A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit. * @public * @since 3.0.015 (2008-06-06) */ @@ -2067,7 +2084,7 @@ class TCPDF { /** * Change the format of the current page - * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() documentation or an array of two numbers (width, height) or an array containing the following measures and options:
          + * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() documentation or an array of two numbers (width, height) or an array containing the following measures and options:
            *
          • ['format'] = page format name (one of the above);
          • *
          • ['Rotate'] : The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.
          • *
          • ['PZ'] : The page's preferred zoom (magnification) factor.
          • @@ -2111,7 +2128,7 @@ class TCPDF { *
          • ['trans']['SS'] : (Fly transition style only) The starting or ending scale at which the changes shall be drawn. If M specifies an inward transition, the scale of the changes drawn shall progress from SS to 1.0 over the course of the transition. If M specifies an outward transition, the scale of the changes drawn shall progress from 1.0 to SS over the course of the transition. Default: 1.0.
          • *
          • ['trans']['B'] : (Fly transition style only) If true, the area that shall be flown in is rectangular and opaque. Default: false.
          • *
          - * @param $orientation (string) page orientation. Possible values are (case insensitive):
            + * @param string $orientation page orientation. Possible values are (case insensitive):
              *
            • P or Portrait (default)
            • *
            • L or Landscape
            • *
            • '' (empty string) for automatic orientation
            • @@ -2228,13 +2245,13 @@ class TCPDF { /** * Set page orientation. - * @param $orientation (string) page orientation. Possible values are (case insensitive):
              • P or Portrait (default)
              • L or Landscape
              • '' (empty string) for automatic orientation
              - * @param $autopagebreak (boolean) Boolean indicating if auto-page-break mode should be on or off. - * @param $bottommargin (float) bottom margin of the page. + * @param string $orientation page orientation. Possible values are (case insensitive):
              • P or Portrait (default)
              • L or Landscape
              • '' (empty string) for automatic orientation
              + * @param boolean|null $autopagebreak Boolean indicating if auto-page-break mode should be on or off. + * @param float|null $bottommargin bottom margin of the page. * @public * @since 3.0.015 (2008-06-06) */ - public function setPageOrientation($orientation, $autopagebreak='', $bottommargin='') { + public function setPageOrientation($orientation, $autopagebreak=null, $bottommargin=null) { if (!isset($this->pagedim[$this->page]['MediaBox'])) { // the boundaries of the physical medium on which the page shall be displayed or printed $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true, $this->k, $this->pagedim); @@ -2306,7 +2323,7 @@ class TCPDF { $bottommargin = 2 * 28.35 / $this->k; } } - $this->SetAutoPageBreak($autopagebreak, $bottommargin); + $this->setAutoPageBreak($autopagebreak, $bottommargin); // store page dimensions $this->pagedim[$this->page]['w'] = $this->wPt; $this->pagedim[$this->page]['h'] = $this->hPt; @@ -2336,7 +2353,7 @@ class TCPDF { * \p{Lo} : Unicode letter or ideograph that does not have lowercase and uppercase variants. Is used to chunk chinese words. * \xa0 : Unicode Character 'NO-BREAK SPACE' (U+00A0) * - * @param $re (string) regular expression (leave empty for default). + * @param string $re regular expression (leave empty for default). * @public * @since 4.6.016 (2009-06-15) */ @@ -2360,8 +2377,8 @@ class TCPDF { /** * Enable or disable Right-To-Left language mode - * @param $enable (Boolean) if true enable Right-To-Left language mode. - * @param $resetx (Boolean) if true reset the X position on direction change. + * @param boolean $enable if true enable Right-To-Left language mode. + * @param boolean $resetx if true reset the X position on direction change. * @public * @since 2.0.000 (2008-01-03) */ @@ -2377,7 +2394,7 @@ class TCPDF { /** * Return the RTL status - * @return boolean + * @return bool * @public * @since 4.0.012 (2008-07-24) */ @@ -2387,7 +2404,7 @@ class TCPDF { /** * Force temporary RTL language direction - * @param $mode (mixed) can be false, 'L' for LTR or 'R' for RTL + * @param false|string $mode can be false, 'L' for LTR or 'R' for RTL * @public * @since 2.1.000 (2008-01-09) */ @@ -2419,7 +2436,7 @@ class TCPDF { /** * Return the current temporary RTL status - * @return boolean + * @return bool * @public * @since 4.8.014 (2009-11-04) */ @@ -2429,7 +2446,7 @@ class TCPDF { /** * Set the last cell height. - * @param $h (float) cell height. + * @param float $h cell height. * @author Nicola Asuni * @public * @since 1.53.0.TC034 @@ -2440,9 +2457,10 @@ class TCPDF { /** * Return the cell height - * @param $fontsize (int) Font size in internal units - * @param $padding (boolean) If true add cell padding + * @param int $fontsize Font size in internal units + * @param boolean $padding If true add cell padding * @public + * @return float */ public function getCellHeight($fontsize, $padding=TRUE) { $height = ($fontsize * $this->cell_height_ratio); @@ -2463,7 +2481,7 @@ class TCPDF { /** * Get the last cell height. - * @return last cell height + * @return float last cell height * @public * @since 4.0.017 (2008-08-05) */ @@ -2473,7 +2491,7 @@ class TCPDF { /** * Set the adjusting factor to convert pixels to user units. - * @param $scale (float) adjusting factor to convert pixels to user units. + * @param float $scale adjusting factor to convert pixels to user units. * @author Nicola Asuni * @public * @since 1.5.2 @@ -2496,13 +2514,13 @@ class TCPDF { /** * Returns an array of page dimensions: *
              • $this->pagedim[$this->page]['w'] = page width in points
              • $this->pagedim[$this->page]['h'] = height in points
              • $this->pagedim[$this->page]['wk'] = page width in user units
              • $this->pagedim[$this->page]['hk'] = page height in user units
              • $this->pagedim[$this->page]['tm'] = top margin
              • $this->pagedim[$this->page]['bm'] = bottom margin
              • $this->pagedim[$this->page]['lm'] = left margin
              • $this->pagedim[$this->page]['rm'] = right margin
              • $this->pagedim[$this->page]['pb'] = auto page break
              • $this->pagedim[$this->page]['or'] = page orientation
              • $this->pagedim[$this->page]['olm'] = original left margin
              • $this->pagedim[$this->page]['orm'] = original right margin
              • $this->pagedim[$this->page]['Rotate'] = The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.
              • $this->pagedim[$this->page]['PZ'] = The page's preferred zoom (magnification) factor.
              • $this->pagedim[$this->page]['trans'] : the style and duration of the visual transition to use when moving from another page to the given page during a presentation
                • $this->pagedim[$this->page]['trans']['Dur'] = The page's display duration (also called its advance timing): the maximum length of time, in seconds, that the page shall be displayed during presentations before the viewer application shall automatically advance to the next page.
                • $this->pagedim[$this->page]['trans']['S'] = transition style : Split, Blinds, Box, Wipe, Dissolve, Glitter, R, Fly, Push, Cover, Uncover, Fade
                • $this->pagedim[$this->page]['trans']['D'] = The duration of the transition effect, in seconds.
                • $this->pagedim[$this->page]['trans']['Dm'] = (Split and Blinds transition styles only) The dimension in which the specified transition effect shall occur: H = Horizontal, V = Vertical. Default value: H.
                • $this->pagedim[$this->page]['trans']['M'] = (Split, Box and Fly transition styles only) The direction of motion for the specified transition effect: I = Inward from the edges of the page, O = Outward from the center of the pageDefault value: I.
                • $this->pagedim[$this->page]['trans']['Di'] = (Wipe, Glitter, Fly, Cover, Uncover and Push transition styles only) The direction in which the specified transition effect shall moves, expressed in degrees counterclockwise starting from a left-to-right direction. If the value is a number, it shall be one of: 0 = Left to right, 90 = Bottom to top (Wipe only), 180 = Right to left (Wipe only), 270 = Top to bottom, 315 = Top-left to bottom-right (Glitter only). If the value is a name, it shall be None, which is relevant only for the Fly transition when the value of SS is not 1.0. Default value: 0.
                • $this->pagedim[$this->page]['trans']['SS'] = (Fly transition style only) The starting or ending scale at which the changes shall be drawn. If M specifies an inward transition, the scale of the changes drawn shall progress from SS to 1.0 over the course of the transition. If M specifies an outward transition, the scale of the changes drawn shall progress from 1.0 to SS over the course of the transition. Default: 1.0.
                • $this->pagedim[$this->page]['trans']['B'] = (Fly transition style only) If true, the area that shall be flown in is rectangular and opaque. Default: false.
              • $this->pagedim[$this->page]['MediaBox'] : the boundaries of the physical medium on which the page shall be displayed or printed
                • $this->pagedim[$this->page]['MediaBox']['llx'] = lower-left x coordinate in points
                • $this->pagedim[$this->page]['MediaBox']['lly'] = lower-left y coordinate in points
                • $this->pagedim[$this->page]['MediaBox']['urx'] = upper-right x coordinate in points
                • $this->pagedim[$this->page]['MediaBox']['ury'] = upper-right y coordinate in points
              • $this->pagedim[$this->page]['CropBox'] : the visible region of default user space
                • $this->pagedim[$this->page]['CropBox']['llx'] = lower-left x coordinate in points
                • $this->pagedim[$this->page]['CropBox']['lly'] = lower-left y coordinate in points
                • $this->pagedim[$this->page]['CropBox']['urx'] = upper-right x coordinate in points
                • $this->pagedim[$this->page]['CropBox']['ury'] = upper-right y coordinate in points
              • $this->pagedim[$this->page]['BleedBox'] : the region to which the contents of the page shall be clipped when output in a production environment
                • $this->pagedim[$this->page]['BleedBox']['llx'] = lower-left x coordinate in points
                • $this->pagedim[$this->page]['BleedBox']['lly'] = lower-left y coordinate in points
                • $this->pagedim[$this->page]['BleedBox']['urx'] = upper-right x coordinate in points
                • $this->pagedim[$this->page]['BleedBox']['ury'] = upper-right y coordinate in points
              • $this->pagedim[$this->page]['TrimBox'] : the intended dimensions of the finished page after trimming
                • $this->pagedim[$this->page]['TrimBox']['llx'] = lower-left x coordinate in points
                • $this->pagedim[$this->page]['TrimBox']['lly'] = lower-left y coordinate in points
                • $this->pagedim[$this->page]['TrimBox']['urx'] = upper-right x coordinate in points
                • $this->pagedim[$this->page]['TrimBox']['ury'] = upper-right y coordinate in points
              • $this->pagedim[$this->page]['ArtBox'] : the extent of the page's meaningful content
                • $this->pagedim[$this->page]['ArtBox']['llx'] = lower-left x coordinate in points
                • $this->pagedim[$this->page]['ArtBox']['lly'] = lower-left y coordinate in points
                • $this->pagedim[$this->page]['ArtBox']['urx'] = upper-right x coordinate in points
                • $this->pagedim[$this->page]['ArtBox']['ury'] = upper-right y coordinate in points
              - * @param $pagenum (int) page number (empty = current page) + * @param int|null $pagenum page number (empty = current page) * @return array of page dimensions. * @author Nicola Asuni * @public * @since 4.5.027 (2009-03-16) */ - public function getPageDimensions($pagenum='') { + public function getPageDimensions($pagenum=null) { if (empty($pagenum)) { $pagenum = $this->page; } @@ -2511,14 +2529,14 @@ class TCPDF { /** * Returns the page width in units. - * @param $pagenum (int) page number (empty = current page) + * @param int|null $pagenum page number (empty = current page) * @return int page width. * @author Nicola Asuni * @public * @since 1.5.2 * @see getPageDimensions() */ - public function getPageWidth($pagenum='') { + public function getPageWidth($pagenum=null) { if (empty($pagenum)) { return $this->w; } @@ -2527,14 +2545,14 @@ class TCPDF { /** * Returns the page height in units. - * @param $pagenum (int) page number (empty = current page) + * @param int|null $pagenum page number (empty = current page) * @return int page height. * @author Nicola Asuni * @public * @since 1.5.2 * @see getPageDimensions() */ - public function getPageHeight($pagenum='') { + public function getPageHeight($pagenum=null) { if (empty($pagenum)) { return $this->h; } @@ -2543,14 +2561,14 @@ class TCPDF { /** * Returns the page break margin. - * @param $pagenum (int) page number (empty = current page) + * @param int|null $pagenum page number (empty = current page) * @return int page break margin. * @author Nicola Asuni * @public * @since 1.5.2 * @see getPageDimensions() */ - public function getBreakMargin($pagenum='') { + public function getBreakMargin($pagenum=null) { if (empty($pagenum)) { return $this->bMargin; } @@ -2570,19 +2588,19 @@ class TCPDF { /** * Defines the left, top and right margins. - * @param $left (float) Left margin. - * @param $top (float) Top margin. - * @param $right (float) Right margin. Default value is the left one. - * @param $keepmargins (boolean) if true overwrites the default page margins + * @param float $left Left margin. + * @param float $top Top margin. + * @param float $right Right margin. Default value is the left one. + * @param boolean $keepmargins if true overwrites the default page margins * @public * @since 1.0 * @see SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak() */ - public function SetMargins($left, $top, $right=-1, $keepmargins=false) { + public function setMargins($left, $top, $right=null, $keepmargins=false) { //Set left, top and right margins $this->lMargin = $left; $this->tMargin = $top; - if ($right == -1) { + if ($right == -1 OR $right === null) { $right = $left; } $this->rMargin = $right; @@ -2595,12 +2613,12 @@ class TCPDF { /** * Defines the left margin. The method can be called before creating the first page. If the current abscissa gets out of page, it is brought back to the margin. - * @param $margin (float) The margin. + * @param float $margin The margin. * @public * @since 1.4 * @see SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins() */ - public function SetLeftMargin($margin) { + public function setLeftMargin($margin) { //Set left margin $this->lMargin = $margin; if (($this->page > 0) AND ($this->x < $margin)) { @@ -2610,12 +2628,12 @@ class TCPDF { /** * Defines the top margin. The method can be called before creating the first page. - * @param $margin (float) The margin. + * @param float $margin The margin. * @public * @since 1.5 * @see SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins() */ - public function SetTopMargin($margin) { + public function setTopMargin($margin) { //Set top margin $this->tMargin = $margin; if (($this->page > 0) AND ($this->y < $margin)) { @@ -2625,12 +2643,12 @@ class TCPDF { /** * Defines the right margin. The method can be called before creating the first page. - * @param $margin (float) The margin. + * @param float $margin The margin. * @public * @since 1.5 * @see SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins() */ - public function SetRightMargin($margin) { + public function setRightMargin($margin) { $this->rMargin = $margin; if (($this->page > 0) AND ($this->x > ($this->w - $margin))) { $this->x = $this->w - $margin; @@ -2639,12 +2657,12 @@ class TCPDF { /** * Set the same internal Cell padding for top, right, bottom, left- - * @param $pad (float) internal padding. + * @param float $pad internal padding. * @public * @since 2.1.000 (2008-01-09) * @see getCellPaddings(), setCellPaddings() */ - public function SetCellPadding($pad) { + public function setCellPadding($pad) { if ($pad >= 0) { $this->cell_padding['L'] = $pad; $this->cell_padding['T'] = $pad; @@ -2655,25 +2673,25 @@ class TCPDF { /** * Set the internal Cell paddings. - * @param $left (float) left padding - * @param $top (float) top padding - * @param $right (float) right padding - * @param $bottom (float) bottom padding + * @param float|null $left left padding + * @param float|null $top top padding + * @param float|null $right right padding + * @param float|null $bottom bottom padding * @public * @since 5.9.000 (2010-10-03) * @see getCellPaddings(), SetCellPadding() */ - public function setCellPaddings($left='', $top='', $right='', $bottom='') { - if (($left !== '') AND ($left >= 0)) { + public function setCellPaddings($left=null, $top=null, $right=null, $bottom=null) { + if (!TCPDF_STATIC::empty_string($left) AND ($left >= 0)) { $this->cell_padding['L'] = $left; } - if (($top !== '') AND ($top >= 0)) { + if (!TCPDF_STATIC::empty_string($top) AND ($top >= 0)) { $this->cell_padding['T'] = $top; } - if (($right !== '') AND ($right >= 0)) { + if (!TCPDF_STATIC::empty_string($right) AND ($right >= 0)) { $this->cell_padding['R'] = $right; } - if (($bottom !== '') AND ($bottom >= 0)) { + if (!TCPDF_STATIC::empty_string($bottom) AND ($bottom >= 0)) { $this->cell_padding['B'] = $bottom; } } @@ -2691,25 +2709,25 @@ class TCPDF { /** * Set the internal Cell margins. - * @param $left (float) left margin - * @param $top (float) top margin - * @param $right (float) right margin - * @param $bottom (float) bottom margin + * @param float|null $left left margin + * @param float|null $top top margin + * @param float|null $right right margin + * @param float|null $bottom bottom margin * @public * @since 5.9.000 (2010-10-03) * @see getCellMargins() */ - public function setCellMargins($left='', $top='', $right='', $bottom='') { - if (($left !== '') AND ($left >= 0)) { + public function setCellMargins($left=null, $top=null, $right=null, $bottom=null) { + if (!TCPDF_STATIC::empty_string($left) AND ($left >= 0)) { $this->cell_margin['L'] = $left; } - if (($top !== '') AND ($top >= 0)) { + if (!TCPDF_STATIC::empty_string($top) AND ($top >= 0)) { $this->cell_margin['T'] = $top; } - if (($right !== '') AND ($right >= 0)) { + if (!TCPDF_STATIC::empty_string($right) AND ($right >= 0)) { $this->cell_margin['R'] = $right; } - if (($bottom !== '') AND ($bottom >= 0)) { + if (!TCPDF_STATIC::empty_string($bottom) AND ($bottom >= 0)) { $this->cell_margin['B'] = $bottom; } } @@ -2727,8 +2745,8 @@ class TCPDF { /** * Adjust the internal Cell padding array to take account of the line width. - * @param $brd (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @return array of adjustments + * @param string|array|int $brd Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @return void|array array of adjustments * @public * @since 5.9.000 (2010-10-03) */ @@ -2744,7 +2762,11 @@ class TCPDF { $newbrd[$brd[$i]] = true; } $brd = $newbrd; - } elseif (($brd === 1) OR ($brd === true) OR (is_numeric($brd) AND (intval($brd) > 0))) { + } elseif ( + ($brd === 1) + || ($brd === true) + || (is_numeric($brd) && ((int)$brd > 0)) + ) { $brd = array('LRTB' => true); } if (!is_array($brd)) { @@ -2762,7 +2784,7 @@ class TCPDF { // process borders foreach ($brd as $border => $style) { $line_width = $this->LineWidth; - if (is_array($style) AND isset($style['width'])) { + if (is_array($style) && isset($style['width'])) { // get border width $line_width = $style['width']; } @@ -2783,31 +2805,54 @@ class TCPDF { } } // correct internal cell padding if required to avoid overlap between text and lines - if ((strpos($border,'T') !== false) AND ($this->cell_padding['T'] < $adj)) { + if ( + is_numeric($this->cell_padding['T']) + && ($this->cell_padding['T'] < $adj) + && (strpos($border, 'T') !== false) + ) { $this->cell_padding['T'] = $adj; } - if ((strpos($border,'R') !== false) AND ($this->cell_padding['R'] < $adj)) { + if ( + is_numeric($this->cell_padding['R']) + && ($this->cell_padding['R'] < $adj) + && (strpos($border, 'R') !== false) + ) { $this->cell_padding['R'] = $adj; } - if ((strpos($border,'B') !== false) AND ($this->cell_padding['B'] < $adj)) { + if ( + is_numeric($this->cell_padding['B']) + && ($this->cell_padding['B'] < $adj) + && (strpos($border, 'B') !== false) + ) { $this->cell_padding['B'] = $adj; } - if ((strpos($border,'L') !== false) AND ($this->cell_padding['L'] < $adj)) { + if ( + is_numeric($this->cell_padding['L']) + && ($this->cell_padding['L'] < $adj) + && (strpos($border, 'L') !== false) + ) { $this->cell_padding['L'] = $adj; } + } - return array('T' => ($this->cell_padding['T'] - $cp['T']), 'R' => ($this->cell_padding['R'] - $cp['R']), 'B' => ($this->cell_padding['B'] - $cp['B']), 'L' => ($this->cell_padding['L'] - $cp['L'])); + + return array( + 'T' => ($this->cell_padding['T'] - $cp['T']), + 'R' => ($this->cell_padding['R'] - $cp['R']), + 'B' => ($this->cell_padding['B'] - $cp['B']), + 'L' => ($this->cell_padding['L'] - $cp['L']), + ); } /** * Enables or disables the automatic page breaking mode. When enabling, the second parameter is the distance from the bottom of the page that defines the triggering limit. By default, the mode is on and the margin is 2 cm. - * @param $auto (boolean) Boolean indicating if mode should be on or off. - * @param $margin (float) Distance from the bottom of the page. + * @param boolean $auto Boolean indicating if mode should be on or off. + * @param float $margin Distance from the bottom of the page. * @public * @since 1.0 * @see Cell(), MultiCell(), AcceptPageBreak() */ - public function SetAutoPageBreak($auto, $margin=0) { + public function setAutoPageBreak($auto, $margin=0) { $this->AutoPageBreak = $auto ? true : false; $this->bMargin = $margin; $this->PageBreakTrigger = $this->h - $margin; @@ -2815,7 +2860,7 @@ class TCPDF { /** * Return the auto-page-break mode (true or false). - * @return boolean auto-page-break mode + * @return bool auto-page-break mode * @public * @since 5.9.088 */ @@ -2825,13 +2870,13 @@ class TCPDF { /** * Defines the way the document is to be displayed by the viewer. - * @param $zoom (mixed) The zoom to use. It can be one of the following string values or a number indicating the zooming factor to use.
              • fullpage: displays the entire page on screen
              • fullwidth: uses maximum width of window
              • real: uses real size (equivalent to 100% zoom)
              • default: uses viewer default mode
              - * @param $layout (string) The page layout. Possible values are:
              • SinglePage Display one page at a time
              • OneColumn Display the pages in one column
              • TwoColumnLeft Display the pages in two columns, with odd-numbered pages on the left
              • TwoColumnRight Display the pages in two columns, with odd-numbered pages on the right
              • TwoPageLeft (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left
              • TwoPageRight (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right
              - * @param $mode (string) A name object specifying how the document should be displayed when opened:
              • UseNone Neither document outline nor thumbnail images visible
              • UseOutlines Document outline visible
              • UseThumbs Thumbnail images visible
              • FullScreen Full-screen mode, with no menu bar, window controls, or any other window visible
              • UseOC (PDF 1.5) Optional content group panel visible
              • UseAttachments (PDF 1.6) Attachments panel visible
              + * @param mixed $zoom The zoom to use. It can be one of the following string values or a number indicating the zooming factor to use.
              • fullpage: displays the entire page on screen
              • fullwidth: uses maximum width of window
              • real: uses real size (equivalent to 100% zoom)
              • default: uses viewer default mode
              + * @param string $layout The page layout. Possible values are:
              • SinglePage Display one page at a time
              • OneColumn Display the pages in one column
              • TwoColumnLeft Display the pages in two columns, with odd-numbered pages on the left
              • TwoColumnRight Display the pages in two columns, with odd-numbered pages on the right
              • TwoPageLeft (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left
              • TwoPageRight (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right
              + * @param string $mode A name object specifying how the document should be displayed when opened:
              • UseNone Neither document outline nor thumbnail images visible
              • UseOutlines Document outline visible
              • UseThumbs Thumbnail images visible
              • FullScreen Full-screen mode, with no menu bar, window controls, or any other window visible
              • UseOC (PDF 1.5) Optional content group panel visible
              • UseAttachments (PDF 1.6) Attachments panel visible
              * @public * @since 1.2 */ - public function SetDisplayMode($zoom, $layout='SinglePage', $mode='UseNone') { + public function setDisplayMode($zoom, $layout='SinglePage', $mode='UseNone') { if (($zoom == 'fullpage') OR ($zoom == 'fullwidth') OR ($zoom == 'real') OR ($zoom == 'default') OR (!is_string($zoom))) { $this->ZoomMode = $zoom; } else { @@ -2844,11 +2889,11 @@ class TCPDF { /** * Activates or deactivates page compression. When activated, the internal representation of each page is compressed, which leads to a compression ratio of about 2 for the resulting document. Compression is on by default. * Note: the Zlib extension is required for this feature. If not present, compression will be turned off. - * @param $compress (boolean) Boolean indicating if compression must be enabled. + * @param boolean $compress Boolean indicating if compression must be enabled. * @public * @since 1.4 */ - public function SetCompression($compress=true) { + public function setCompression($compress=true) { $this->compress = false; if (function_exists('gzcompress')) { if ($compress) { @@ -2861,7 +2906,7 @@ class TCPDF { /** * Set flag to force sRGB_IEC61966-2.1 black scaled ICC color profile for the whole document. - * @param $mode (boolean) If true force sRGB output intent. + * @param boolean $mode If true force sRGB output intent. * @public * @since 5.9.121 (2011-09-28) */ @@ -2872,72 +2917,84 @@ class TCPDF { /** * Turn on/off Unicode mode for document information dictionary (meta tags). * This has effect only when unicode mode is set to false. - * @param $unicode (boolean) if true set the meta information in Unicode + * @param boolean $unicode if true set the meta information in Unicode * @since 5.9.027 (2010-12-01) * @public */ - public function SetDocInfoUnicode($unicode=true) { + public function setDocInfoUnicode($unicode=true) { $this->docinfounicode = $unicode ? true : false; } /** * Defines the title of the document. - * @param $title (string) The title. + * @param string $title The title. * @public * @since 1.2 * @see SetAuthor(), SetCreator(), SetKeywords(), SetSubject() */ - public function SetTitle($title) { + public function setTitle($title) { $this->title = $title; } /** * Defines the subject of the document. - * @param $subject (string) The subject. + * @param string $subject The subject. * @public * @since 1.2 * @see SetAuthor(), SetCreator(), SetKeywords(), SetTitle() */ - public function SetSubject($subject) { + public function setSubject($subject) { $this->subject = $subject; } /** * Defines the author of the document. - * @param $author (string) The name of the author. + * @param string $author The name of the author. * @public * @since 1.2 * @see SetCreator(), SetKeywords(), SetSubject(), SetTitle() */ - public function SetAuthor($author) { + public function setAuthor($author) { $this->author = $author; } /** * Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'. - * @param $keywords (string) The list of keywords. + * @param string $keywords The list of keywords. * @public * @since 1.2 * @see SetAuthor(), SetCreator(), SetSubject(), SetTitle() */ - public function SetKeywords($keywords) { + public function setKeywords($keywords) { $this->keywords = $keywords; } /** * Defines the creator of the document. This is typically the name of the application that generates the PDF. - * @param $creator (string) The name of the creator. + * @param string $creator The name of the creator. * @public * @since 1.2 * @see SetAuthor(), SetKeywords(), SetSubject(), SetTitle() */ - public function SetCreator($creator) { + public function setCreator($creator) { $this->creator = $creator; } + /** + * Whether to allow local file path in image html tags, when prefixed with file:// + * + * @param bool $allowLocalFiles true, when local files should be allowed. Otherwise false. + * @public + * @since 6.4 + */ + public function setAllowLocalFiles($allowLocalFiles) { + $this->allowLocalFiles = (bool) $allowLocalFiles; + } + + /** * Throw an exception or print an error message and die if the K_TCPDF_PARSER_THROW_EXCEPTION_ERROR constant is set to true. - * @param $msg (string) The error message + * @param string $msg The error message * @public * @since 1.0 */ @@ -2984,13 +3041,13 @@ class TCPDF { $gvars = $this->getGraphicVars(); $this->setEqualColumns(); $this->lastpage(true); - $this->SetAutoPageBreak(false); + $this->setAutoPageBreak(false); $this->x = 0; $this->y = $this->h - (1 / $this->k); $this->lMargin = 0; $this->_outSaveGraphicsState(); $font = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica'; - $this->SetFont($font, '', 1); + $this->setFont($font, '', 1); $this->setTextRenderingMode(0, false, false); $msg = "\x50\x6f\x77\x65\x72\x65\x64\x20\x62\x79\x20\x54\x43\x50\x44\x46\x20\x28\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29"; $lnk = "\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67"; @@ -3009,8 +3066,8 @@ class TCPDF { /** * Move pointer at the specified document page and update page dimensions. - * @param $pnum (int) page number (1 ... numpages) - * @param $resetmargins (boolean) if true reset left, right, top margins and Y position. + * @param int $pnum page number (1 ... numpages) + * @param boolean $resetmargins if true reset left, right, top margins and Y position. * @public * @since 2.1.000 (2008-01-07) * @see getPage(), lastpage(), getNumPages() @@ -3035,13 +3092,13 @@ class TCPDF { $this->original_rMargin = $this->pagedim[$this->page]['orm']; $this->AutoPageBreak = $this->pagedim[$this->page]['pb']; $this->CurOrientation = $this->pagedim[$this->page]['or']; - $this->SetAutoPageBreak($this->AutoPageBreak, $this->bMargin); + $this->setAutoPageBreak($this->AutoPageBreak, $this->bMargin); // restore graphic settings //$this->setGraphicVars($gvars); if ($resetmargins) { $this->lMargin = $this->pagedim[$this->page]['olm']; $this->rMargin = $this->pagedim[$this->page]['orm']; - $this->SetY($this->tMargin); + $this->setY($this->tMargin); } else { // account for booklet mode if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) { @@ -3057,7 +3114,7 @@ class TCPDF { /** * Reset pointer to the last document page. - * @param $resetmargins (boolean) if true reset left, right, top margins and Y position. + * @param boolean $resetmargins if true reset left, right, top margins and Y position. * @public * @since 2.0.000 (2008-01-04) * @see setPage(), getPage(), getNumPages() @@ -3090,9 +3147,9 @@ class TCPDF { /** * Adds a new TOC (Table Of Content) page to the document. - * @param $orientation (string) page orientation. - * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). - * @param $keepmargins (boolean) if true overwrites the default page margins with the current margins + * @param string $orientation page orientation. + * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). + * @param boolean $keepmargins if true overwrites the default page margins with the current margins * @public * @since 5.0.001 (2010-05-06) * @see AddPage(), startPage(), endPage(), endTOCPage() @@ -3114,10 +3171,10 @@ class TCPDF { /** * Adds a new page to the document. If a page is already present, the Footer() method is called first to output the footer (if enabled). Then the page is added, the current position set to the top-left corner according to the left and top margins (or top-right if in RTL mode), and Header() is called to display the header (if enabled). * The origin of the coordinate system is at the top-left corner (or top-right for RTL) and increasing ordinates go downwards. - * @param $orientation (string) page orientation. Possible values are (case insensitive):
              • P or PORTRAIT (default)
              • L or LANDSCAPE
              - * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). - * @param $keepmargins (boolean) if true overwrites the default page margins with the current margins - * @param $tocpage (boolean) if true set the tocpage state to true (the added page will be used to display Table Of Content). + * @param string $orientation page orientation. Possible values are (case insensitive):
              • P or PORTRAIT (default)
              • L or LANDSCAPE
              + * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). + * @param boolean $keepmargins if true overwrites the default page margins with the current margins + * @param boolean $tocpage if true set the tocpage state to true (the added page will be used to display Table Of Content). * @public * @since 1.0 * @see startPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat() @@ -3141,7 +3198,7 @@ class TCPDF { /** * Terminate the current page - * @param $tocpage (boolean) if true set the tocpage state to false (end the page used to display Table Of Content). + * @param boolean $tocpage if true set the tocpage state to false (end the page used to display Table Of Content). * @public * @since 4.2.010 (2008-11-14) * @see AddPage(), startPage(), addTOCPage(), endTOCPage() @@ -3165,9 +3222,9 @@ class TCPDF { /** * Starts a new page to the document. The page must be closed using the endPage() function. * The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards. - * @param $orientation (string) page orientation. Possible values are (case insensitive):
              • P or PORTRAIT (default)
              • L or LANDSCAPE
              - * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). - * @param $tocpage (boolean) if true the page is designated to contain the Table-Of-Content. + * @param string $orientation page orientation. Possible values are (case insensitive):
              • P or PORTRAIT (default)
              • L or LANDSCAPE
              + * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). + * @param boolean $tocpage if true the page is designated to contain the Table-Of-Content. * @since 4.2.010 (2008-11-14) * @see AddPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat() * @public @@ -3204,7 +3261,7 @@ class TCPDF { if ($this->numpages > $this->page) { // this page has been already added $this->setPage($this->page + 1); - $this->SetY($this->tMargin); + $this->setY($this->tMargin); return; } // start a new page @@ -3252,7 +3309,7 @@ class TCPDF { /** * Set start-writing mark on selected page. * Borders and fills are always created after content and inserted on the position marked by this method. - * @param $page (int) page number (default is the current page) + * @param int $page page number (default is the current page) * @protected * @since 4.6.021 (2009-07-20) */ @@ -3269,12 +3326,12 @@ class TCPDF { /** * Set header data. - * @param $ln (string) header image logo - * @param $lw (string) header image logo width in mm - * @param $ht (string) string to print as title on document header - * @param $hs (string) string to print on document header - * @param $tc (array) RGB array color for text. - * @param $lc (array) RGB array color for line. + * @param string $ln header image logo + * @param int $lw header image logo width in mm + * @param string $ht string to print as title on document header + * @param string $hs string to print on document header + * @param int[] $tc RGB array color for text. + * @param int[] $lc RGB array color for line. * @public */ public function setHeaderData($ln='', $lw=0, $ht='', $hs='', $tc=array(0,0,0), $lc=array(0,0,0)) { @@ -3288,8 +3345,8 @@ class TCPDF { /** * Set footer data. - * @param $tc (array) RGB array color for text. - * @param $lc (array) RGB array color for line. + * @param int[] $tc RGB array color for text. + * @param int[] $lc RGB array color for line. * @public */ public function setFooterData($tc=array(0,0,0), $lc=array(0,0,0)) { @@ -3300,7 +3357,7 @@ class TCPDF { /** * Returns header data: *
              • $ret['logo'] = logo image
              • $ret['logo_width'] = width of the image logo in user units
              • $ret['title'] = header title
              • $ret['string'] = header description string
              - * @return array() + * @return array * @public * @since 4.0.012 (2008-07-24) */ @@ -3318,7 +3375,7 @@ class TCPDF { /** * Set header margin. * (minimum distance between header and top page margin) - * @param $hm (int) distance in user units + * @param int $hm distance in user units * @public */ public function setHeaderMargin($hm=10) { @@ -3338,7 +3395,7 @@ class TCPDF { /** * Set footer margin. * (minimum distance between footer and bottom page margin) - * @param $fm (int) distance in user units + * @param int $fm distance in user units * @public */ public function setFooterMargin($fm=10) { @@ -3356,7 +3413,7 @@ class TCPDF { } /** * Set a flag to print page header. - * @param $val (boolean) set to true to print the page header (default), false otherwise. + * @param boolean $val set to true to print the page header (default), false otherwise. * @public */ public function setPrintHeader($val=true) { @@ -3365,7 +3422,7 @@ class TCPDF { /** * Set a flag to print page footer. - * @param $val (boolean) set to true to print the page footer (default), false otherwise. + * @param boolean $val set to true to print the page footer (default), false otherwise. * @public */ public function setPrintFooter($val=true) { @@ -3400,7 +3457,7 @@ class TCPDF { /** * Set a flag to automatically reset the xobject template used by Header() method at each page. - * @param $val (boolean) set to true to reset Header xobject template at each page, false otherwise. + * @param boolean $val set to true to reset Header xobject template at each page, false otherwise. * @public */ public function setHeaderTemplateAutoreset($val=true) { @@ -3445,22 +3502,22 @@ class TCPDF { $header_x = $this->original_lMargin + ($headerdata['logo_width'] * 1.1); } $cw = $this->w - $this->original_lMargin - $this->original_rMargin - ($headerdata['logo_width'] * 1.1); - $this->SetTextColorArray($this->header_text_color); + $this->setTextColorArray($this->header_text_color); // header title - $this->SetFont($headerfont[0], 'B', $headerfont[2] + 1); - $this->SetX($header_x); + $this->setFont($headerfont[0], 'B', $headerfont[2] + 1); + $this->setX($header_x); $this->Cell($cw, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0); // header string - $this->SetFont($headerfont[0], $headerfont[1], $headerfont[2]); - $this->SetX($header_x); + $this->setFont($headerfont[0], $headerfont[1], $headerfont[2]); + $this->setX($header_x); $this->MultiCell($cw, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false, true, 0, 'T', false); // print an ending header line - $this->SetLineStyle(array('width' => 0.85 / $this->k, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $headerdata['line_color'])); - $this->SetY((2.835 / $this->k) + max($imgy, $this->y)); + $this->setLineStyle(array('width' => 0.85 / $this->k, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $headerdata['line_color'])); + $this->setY((2.835 / $this->k) + max($imgy, $this->y)); if ($this->rtl) { - $this->SetX($this->original_rMargin); + $this->setX($this->original_rMargin); } else { - $this->SetX($this->original_lMargin); + $this->setX($this->original_lMargin); } $this->Cell(($this->w - $this->original_lMargin - $this->original_rMargin), 0, '', 'T', 0, 'C'); $this->endTemplate(); @@ -3491,10 +3548,10 @@ class TCPDF { */ public function Footer() { $cur_y = $this->y; - $this->SetTextColorArray($this->footer_text_color); + $this->setTextColorArray($this->footer_text_color); //set style for cell border $line_width = (0.85 / $this->k); - $this->SetLineStyle(array('width' => $line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $this->footer_line_color)); + $this->setLineStyle(array('width' => $line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $this->footer_line_color)); //print document barcode $barcode = $this->getBarcode(); if (!empty($barcode)) { @@ -3520,13 +3577,13 @@ class TCPDF { } else { $pagenumtxt = $w_page.$this->getPageNumGroupAlias().' / '.$this->getPageGroupAlias(); } - $this->SetY($cur_y); + $this->setY($cur_y); //Print page number if ($this->getRTL()) { - $this->SetX($this->original_rMargin); + $this->setX($this->original_rMargin); $this->Cell(0, 0, $pagenumtxt, 'T', 0, 'L'); } else { - $this->SetX($this->original_lMargin); + $this->setX($this->original_lMargin); $this->Cell(0, 0, $this->getAliasRightShift().$pagenumtxt, 'T', 0, 'R'); } } @@ -3549,20 +3606,20 @@ class TCPDF { $this->_outSaveGraphicsState(); $this->rMargin = $this->original_rMargin; $this->lMargin = $this->original_lMargin; - $this->SetCellPadding(0); + $this->setCellPadding(0); //set current position if ($this->rtl) { - $this->SetXY($this->original_rMargin, $this->header_margin); + $this->setXY($this->original_rMargin, $this->header_margin); } else { - $this->SetXY($this->original_lMargin, $this->header_margin); + $this->setXY($this->original_lMargin, $this->header_margin); } - $this->SetFont($this->header_font[0], $this->header_font[1], $this->header_font[2]); + $this->setFont($this->header_font[0], $this->header_font[1], $this->header_font[2]); $this->Header(); //restore position if ($this->rtl) { - $this->SetXY($this->original_rMargin, $this->tMargin); + $this->setXY($this->original_rMargin, $this->tMargin); } else { - $this->SetXY($this->original_lMargin, $this->tMargin); + $this->setXY($this->original_lMargin, $this->tMargin); } $this->_outRestoreGraphicsState(); $this->lasth = $lasth; @@ -3597,21 +3654,21 @@ class TCPDF { $this->_outSaveGraphicsState(); $this->rMargin = $this->original_rMargin; $this->lMargin = $this->original_lMargin; - $this->SetCellPadding(0); + $this->setCellPadding(0); //set current position $footer_y = $this->h - $this->footer_margin; if ($this->rtl) { - $this->SetXY($this->original_rMargin, $footer_y); + $this->setXY($this->original_rMargin, $footer_y); } else { - $this->SetXY($this->original_lMargin, $footer_y); + $this->setXY($this->original_lMargin, $footer_y); } - $this->SetFont($this->footer_font[0], $this->footer_font[1], $this->footer_font[2]); + $this->setFont($this->footer_font[0], $this->footer_font[1], $this->footer_font[2]); $this->Footer(); //restore position if ($this->rtl) { - $this->SetXY($this->original_rMargin, $this->tMargin); + $this->setXY($this->original_rMargin, $this->tMargin); } else { - $this->SetXY($this->original_lMargin, $this->tMargin); + $this->setXY($this->original_lMargin, $this->tMargin); } $this->_outRestoreGraphicsState(); $this->lasth = $lasth; @@ -3629,7 +3686,7 @@ class TCPDF { /** * Check if we are on the page body (excluding page header and footer). - * @return true if we are not in page header nor in page footer, false otherwise. + * @return bool true if we are not in page header nor in page footer, false otherwise. * @protected * @since 5.9.091 (2011-06-15) */ @@ -3715,7 +3772,7 @@ class TCPDF { /** * Returns the array of spot colors. - * @return (array) Spot colors array. + * @return array Spot colors array. * @public * @since 6.0.038 (2013-09-30) */ @@ -3727,11 +3784,11 @@ class TCPDF { * Defines a new spot color. * It can be expressed in RGB components or gray scale. * The method can be called before the first page is created and the value is retained from page to page. - * @param $name (string) Full name of the spot color. - * @param $c (float) Cyan color for CMYK. Value between 0 and 100. - * @param $m (float) Magenta color for CMYK. Value between 0 and 100. - * @param $y (float) Yellow color for CMYK. Value between 0 and 100. - * @param $k (float) Key (Black) color for CMYK. Value between 0 and 100. + * @param string $name Full name of the spot color. + * @param float $c Cyan color for CMYK. Value between 0 and 100. + * @param float $m Magenta color for CMYK. Value between 0 and 100. + * @param float $y Yellow color for CMYK. Value between 0 and 100. + * @param float $k Key (Black) color for CMYK. Value between 0 and 100. * @public * @since 4.0.024 (2008-09-12) * @see SetDrawSpotColor(), SetFillSpotColor(), SetTextSpotColor() @@ -3745,10 +3802,10 @@ class TCPDF { /** * Set the spot color for the specified type ('draw', 'fill', 'text'). - * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text'). - * @param $name (string) Name of the spot color. - * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default). - * @return (string) PDF color command. + * @param string $type Type of object affected by this color: ('draw', 'fill', 'text'). + * @param string $name Name of the spot color. + * @param float $tint Intensity of the color (from 0 to 100 ; 100 = full intensity by default). + * @return string PDF color command. * @public * @since 5.9.125 (2011-10-03) */ @@ -3792,37 +3849,37 @@ class TCPDF { /** * Defines the spot color used for all drawing operations (lines, rectangles and cell borders). - * @param $name (string) Name of the spot color. - * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default). + * @param string $name Name of the spot color. + * @param float $tint Intensity of the color (from 0 to 100 ; 100 = full intensity by default). * @public * @since 4.0.024 (2008-09-12) * @see AddSpotColor(), SetFillSpotColor(), SetTextSpotColor() */ - public function SetDrawSpotColor($name, $tint=100) { + public function setDrawSpotColor($name, $tint=100) { $this->setSpotColor('draw', $name, $tint); } /** * Defines the spot color used for all filling operations (filled rectangles and cell backgrounds). - * @param $name (string) Name of the spot color. - * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default). + * @param string $name Name of the spot color. + * @param float $tint Intensity of the color (from 0 to 100 ; 100 = full intensity by default). * @public * @since 4.0.024 (2008-09-12) * @see AddSpotColor(), SetDrawSpotColor(), SetTextSpotColor() */ - public function SetFillSpotColor($name, $tint=100) { + public function setFillSpotColor($name, $tint=100) { $this->setSpotColor('fill', $name, $tint); } /** * Defines the spot color used for text. - * @param $name (string) Name of the spot color. - * @param $tint (int) Intensity of the color (from 0 to 100 ; 100 = full intensity by default). + * @param string $name Name of the spot color. + * @param int $tint Intensity of the color (from 0 to 100 ; 100 = full intensity by default). * @public * @since 4.0.024 (2008-09-12) * @see AddSpotColor(), SetDrawSpotColor(), SetFillSpotColor() */ - public function SetTextSpotColor($name, $tint=100) { + public function setTextSpotColor($name, $tint=100) { $this->setSpotColor('text', $name, $tint); } @@ -3830,10 +3887,10 @@ class TCPDF { * Set the color array for the specified type ('draw', 'fill', 'text'). * It can be expressed in RGB, CMYK or GRAY SCALE components. * The method can be called before the first page is created and the value is retained from page to page. - * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text'). - * @param $color (array) Array of colors (1=gray, 3=RGB, 4=CMYK or 5=spotcolor=CMYK+name values). - * @param $ret (boolean) If true do not send the PDF command. - * @return (string) The PDF command or empty string. + * @param string $type Type of object affected by this color: ('draw', 'fill', 'text'). + * @param array $color Array of colors (1=gray, 3=RGB, 4=CMYK or 5=spotcolor=CMYK+name values). + * @param boolean $ret If true do not send the PDF command. + * @return string The PDF command or empty string. * @public * @since 3.1.000 (2008-06-11) */ @@ -3861,14 +3918,14 @@ class TCPDF { * Defines the color used for all drawing operations (lines, rectangles and cell borders). * It can be expressed in RGB, CMYK or GRAY SCALE components. * The method can be called before the first page is created and the value is retained from page to page. - * @param $color (array) Array of colors (1, 3 or 4 values). - * @param $ret (boolean) If true do not send the PDF command. + * @param array $color Array of colors (1, 3 or 4 values). + * @param boolean $ret If true do not send the PDF command. * @return string the PDF command * @public * @since 3.1.000 (2008-06-11) * @see SetDrawColor() */ - public function SetDrawColorArray($color, $ret=false) { + public function setDrawColorArray($color, $ret=false) { return $this->setColorArray('draw', $color, $ret); } @@ -3876,39 +3933,39 @@ class TCPDF { * Defines the color used for all filling operations (filled rectangles and cell backgrounds). * It can be expressed in RGB, CMYK or GRAY SCALE components. * The method can be called before the first page is created and the value is retained from page to page. - * @param $color (array) Array of colors (1, 3 or 4 values). - * @param $ret (boolean) If true do not send the PDF command. + * @param array $color Array of colors (1, 3 or 4 values). + * @param boolean $ret If true do not send the PDF command. * @public * @since 3.1.000 (2008-6-11) * @see SetFillColor() */ - public function SetFillColorArray($color, $ret=false) { + public function setFillColorArray($color, $ret=false) { return $this->setColorArray('fill', $color, $ret); } /** * Defines the color used for text. It can be expressed in RGB components or gray scale. * The method can be called before the first page is created and the value is retained from page to page. - * @param $color (array) Array of colors (1, 3 or 4 values). - * @param $ret (boolean) If true do not send the PDF command. + * @param array $color Array of colors (1, 3 or 4 values). + * @param boolean $ret If true do not send the PDF command. * @public * @since 3.1.000 (2008-6-11) * @see SetFillColor() */ - public function SetTextColorArray($color, $ret=false) { + public function setTextColorArray($color, $ret=false) { return $this->setColorArray('text', $color, $ret); } /** * Defines the color used by the specified type ('draw', 'fill', 'text'). - * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text'). - * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). - * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). - * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). - * @param $col4 (float) KEY (BLACK) color for CMYK (0-100). - * @param $ret (boolean) If true do not send the command. - * @param $name (string) spot color name (if any) - * @return (string) The PDF command or empty string. + * @param string $type Type of object affected by this color: ('draw', 'fill', 'text'). + * @param float $col1 GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). + * @param float $col2 GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). + * @param float $col3 BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). + * @param float $col4 KEY (BLACK) color for CMYK (0-100). + * @param boolean $ret If true do not send the command. + * @param string $name spot color name (if any) + * @return string The PDF command or empty string. * @public * @since 5.9.125 (2011-10-03) */ @@ -3980,7 +4037,7 @@ class TCPDF { } } $this->ColorFlag = ($this->FillColor != $this->TextColor); - if (($type != 'text') AND ($this->state == 2)) { + if (($type != 'text') AND ($this->state == 2) AND $type !== 0) { if (!$ret) { $this->_out($pdfcolor); } @@ -3991,63 +4048,63 @@ class TCPDF { /** * Defines the color used for all drawing operations (lines, rectangles and cell borders). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. - * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). - * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). - * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). - * @param $col4 (float) KEY (BLACK) color for CMYK (0-100). - * @param $ret (boolean) If true do not send the command. - * @param $name (string) spot color name (if any) + * @param float $col1 GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). + * @param float $col2 GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). + * @param float $col3 BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). + * @param float $col4 KEY (BLACK) color for CMYK (0-100). + * @param boolean $ret If true do not send the command. + * @param string $name spot color name (if any) * @return string the PDF command * @public * @since 1.3 * @see SetDrawColorArray(), SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell() */ - public function SetDrawColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { + public function setDrawColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { return $this->setColor('draw', $col1, $col2, $col3, $col4, $ret, $name); } /** * Defines the color used for all filling operations (filled rectangles and cell backgrounds). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. - * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). - * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). - * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). - * @param $col4 (float) KEY (BLACK) color for CMYK (0-100). - * @param $ret (boolean) If true do not send the command. - * @param $name (string) Spot color name (if any). - * @return (string) The PDF command. + * @param float $col1 GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). + * @param float $col2 GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). + * @param float $col3 BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). + * @param float $col4 KEY (BLACK) color for CMYK (0-100). + * @param boolean $ret If true do not send the command. + * @param string $name Spot color name (if any). + * @return string The PDF command. * @public * @since 1.3 * @see SetFillColorArray(), SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell() */ - public function SetFillColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { + public function setFillColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { return $this->setColor('fill', $col1, $col2, $col3, $col4, $ret, $name); } /** * Defines the color used for text. It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. - * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). - * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). - * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). - * @param $col4 (float) KEY (BLACK) color for CMYK (0-100). - * @param $ret (boolean) If true do not send the command. - * @param $name (string) Spot color name (if any). - * @return (string) Empty string. + * @param float $col1 GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). + * @param float $col2 GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). + * @param float $col3 BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). + * @param float $col4 KEY (BLACK) color for CMYK (0-100). + * @param boolean $ret If true do not send the command. + * @param string $name Spot color name (if any). + * @return string Empty string. * @public * @since 1.3 * @see SetTextColorArray(), SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell() */ - public function SetTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { + public function setTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { return $this->setColor('text', $col1, $col2, $col3, $col4, $ret, $name); } /** * Returns the length of a string in user unit. A font must be selected.
              - * @param $s (string) The string whose length is to be computed - * @param $fontname (string) Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained. - * @param $fontstyle (string) Font style. Possible values are (case insensitive):
              • empty string: regular
              • B: bold
              • I: italic
              • U: underline
              • D: line-through
              • O: overline
              or any combination. The default value is regular. - * @param $fontsize (float) Font size in points. The default value is the current size. - * @param $getarray (boolean) if true returns an array of characters widths, if false returns the total length. - * @return mixed int total string length or array of characted widths + * @param string $s The string whose length is to be computed + * @param string $fontname Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained. + * @param string $fontstyle Font style. Possible values are (case insensitive):
              • empty string: regular
              • B: bold
              • I: italic
              • U: underline
              • D: line-through
              • O: overline
              or any combination. The default value is regular. + * @param float $fontsize Font size in points. The default value is the current size. + * @param boolean $getarray if true returns an array of characters widths, if false returns the total length. + * @return float[]|float total string length or array of characted widths * @author Nicola Asuni * @public * @since 1.2 @@ -4058,12 +4115,12 @@ class TCPDF { /** * Returns the string length of an array of chars in user unit or an array of characters widths. A font must be selected.
              - * @param $sa (string) The array of chars whose total length is to be computed - * @param $fontname (string) Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained. - * @param $fontstyle (string) Font style. Possible values are (case insensitive):
              • empty string: regular
              • B: bold
              • I: italic
              • U: underline
              • D: line through
              • O: overline
              or any combination. The default value is regular. - * @param $fontsize (float) Font size in points. The default value is the current size. - * @param $getarray (boolean) if true returns an array of characters widths, if false returns the total length. - * @return mixed int total string length or array of characted widths + * @param array $sa The array of chars whose total length is to be computed + * @param string $fontname Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained. + * @param string $fontstyle Font style. Possible values are (case insensitive):
              • empty string: regular
              • B: bold
              • I: italic
              • U: underline
              • D: line through
              • O: overline
              or any combination. The default value is regular. + * @param float $fontsize Font size in points. The default value is the current size. + * @param boolean $getarray if true returns an array of characters widths, if false returns the total length. + * @return float[]|float total string length or array of characted widths * @author Nicola Asuni * @public * @since 2.4.000 (2008-03-06) @@ -4074,7 +4131,7 @@ class TCPDF { $prev_FontFamily = $this->FontFamily; $prev_FontStyle = $this->FontStyle; $prev_FontSizePt = $this->FontSizePt; - $this->SetFont($fontname, $fontstyle, $fontsize, '', 'default', false); + $this->setFont($fontname, $fontstyle, $fontsize, '', 'default', false); } // convert UTF-8 array to Latin1 if required if ($this->isunicode AND (!$this->isUnicodeFont())) { @@ -4090,7 +4147,7 @@ class TCPDF { } // restore previous values if (!TCPDF_STATIC::empty_string($fontname)) { - $this->SetFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt, '', 'default', false); + $this->setFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt, '', 'default', false); } if ($getarray) { return $wa; @@ -4100,8 +4157,8 @@ class TCPDF { /** * Returns the length of the char in user unit for the current font considering current stretching and spacing (tracking). - * @param $char (int) The char code whose length is to be returned - * @param $notlast (boolean) If false ignore the font-spacing. + * @param int $char The char code whose length is to be returned + * @param boolean $notlast If false ignore the font-spacing. * @return float char width * @author Nicola Asuni * @public @@ -4123,7 +4180,7 @@ class TCPDF { /** * Returns the length of the char in user unit for the current font. - * @param $char (int) The char code whose length is to be returned + * @param int $char The char code whose length is to be returned * @return float char width * @author Nicola Asuni * @public @@ -4134,8 +4191,8 @@ class TCPDF { // SHY character will not be printed return (0); } - if (isset($this->CurrentFont['cw'][$char])) { - $w = $this->CurrentFont['cw'][$char]; + if (isset($this->CurrentFont['cw'][intval($char)])) { + $w = $this->CurrentFont['cw'][intval($char)]; } elseif (isset($this->CurrentFont['dw'])) { // default width $w = $this->CurrentFont['dw']; @@ -4150,7 +4207,7 @@ class TCPDF { /** * Returns the numbero of characters in a string. - * @param $s (string) The input string. + * @param string $s The input string. * @return int number of characters * @public * @since 2.0.0001 (2008-01-07) @@ -4182,11 +4239,11 @@ class TCPDF { * Imports a TrueType, Type1, core, or CID0 font and makes it available. * It is necessary to generate a font definition file first (read /fonts/utils/README.TXT). * The definition file (and the font file itself when embedding) must be present either in the current directory or in the one indicated by K_PATH_FONTS if the constant is defined. If it could not be found, the error "Could not include font definition file" is generated. - * @param $family (string) Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font. - * @param $style (string) Font style. Possible values are (case insensitive):
              • empty string: regular (default)
              • B: bold
              • I: italic
              • BI or IB: bold italic
              - * @param $fontfile (string) The font definition file. By default, the name is built from the family and style, in lower case with no spaces. - * @return array containing the font data, or false in case of error. - * @param $subset (mixed) if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font. + * @param string $family Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font. + * @param string $style Font style. Possible values are (case insensitive):
              • empty string: regular (default)
              • B: bold
              • I: italic
              • BI or IB: bold italic
              + * @param string $fontfile The font definition file. By default, the name is built from the family and style, in lower case with no spaces. + * @return array|false array containing the font data, or false in case of error. + * @param mixed $subset if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font. * @public * @since 1.5 * @see SetFont(), setFontSubsetting() @@ -4436,18 +4493,18 @@ class TCPDF { * The method can be called before the first page is created and the font is retained from page to page. * If you just wish to change the current font size, it is simpler to call SetFontSize(). * Note: for the standard fonts, the font metric files must be accessible. There are three possibilities for this:
              • They are in the current directory (the one where the running script lies)
              • They are in one of the directories defined by the include_path parameter
              • They are in the directory defined by the K_PATH_FONTS constant

              - * @param $family (string) Family font. It can be either a name defined by AddFont() or one of the standard Type1 families (case insensitive):
              • times (Times-Roman)
              • timesb (Times-Bold)
              • timesi (Times-Italic)
              • timesbi (Times-BoldItalic)
              • helvetica (Helvetica)
              • helveticab (Helvetica-Bold)
              • helveticai (Helvetica-Oblique)
              • helveticabi (Helvetica-BoldOblique)
              • courier (Courier)
              • courierb (Courier-Bold)
              • courieri (Courier-Oblique)
              • courierbi (Courier-BoldOblique)
              • symbol (Symbol)
              • zapfdingbats (ZapfDingbats)
              It is also possible to pass an empty string. In that case, the current family is retained. - * @param $style (string) Font style. Possible values are (case insensitive):
              • empty string: regular
              • B: bold
              • I: italic
              • U: underline
              • D: line through
              • O: overline
              or any combination. The default value is regular. Bold and italic styles do not apply to Symbol and ZapfDingbats basic fonts or other fonts when not defined. - * @param $size (float) Font size in points. The default value is the current size. If no size has been specified since the beginning of the document, the value taken is 12 - * @param $fontfile (string) The font definition file. By default, the name is built from the family and style, in lower case with no spaces. - * @param $subset (mixed) if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font. - * @param $out (boolean) if true output the font size command, otherwise only set the font properties. + * @param string $family Family font. It can be either a name defined by AddFont() or one of the standard Type1 families (case insensitive):
              • times (Times-Roman)
              • timesb (Times-Bold)
              • timesi (Times-Italic)
              • timesbi (Times-BoldItalic)
              • helvetica (Helvetica)
              • helveticab (Helvetica-Bold)
              • helveticai (Helvetica-Oblique)
              • helveticabi (Helvetica-BoldOblique)
              • courier (Courier)
              • courierb (Courier-Bold)
              • courieri (Courier-Oblique)
              • courierbi (Courier-BoldOblique)
              • symbol (Symbol)
              • zapfdingbats (ZapfDingbats)
              It is also possible to pass an empty string. In that case, the current family is retained. + * @param string $style Font style. Possible values are (case insensitive):
              • empty string: regular
              • B: bold
              • I: italic
              • U: underline
              • D: line through
              • O: overline
              or any combination. The default value is regular. Bold and italic styles do not apply to Symbol and ZapfDingbats basic fonts or other fonts when not defined. + * @param float|null $size Font size in points. The default value is the current size. If no size has been specified since the beginning of the document, the value taken is 12 + * @param string $fontfile The font definition file. By default, the name is built from the family and style, in lower case with no spaces. + * @param mixed $subset if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font. + * @param boolean $out if true output the font size command, otherwise only set the font properties. * @author Nicola Asuni * @public * @since 1.0 * @see AddFont(), SetFontSize() */ - public function SetFont($family, $style='', $size=null, $fontfile='', $subset='default', $out=true) { + public function setFont($family, $style='', $size=null, $fontfile='', $subset='default', $out=true) { //Select a font; size given in points if ($size === null) { $size = $this->FontSizePt; @@ -4464,18 +4521,18 @@ class TCPDF { $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']); } $this->CurrentFont = $this->getFontBuffer($fontdata['fontkey']); - $this->SetFontSize($size, $out); + $this->setFontSize($size, $out); } /** * Defines the size of the current font. - * @param $size (float) The font size in points. - * @param $out (boolean) if true output the font size command, otherwise only set the font properties. + * @param float $size The font size in points. + * @param boolean $out if true output the font size command, otherwise only set the font properties. * @public * @since 1.0 * @see SetFont() */ - public function SetFontSize($size, $out=true) { + public function setFontSize($size, $out=true) { $size = (float)$size; // font size in points $this->FontSizePt = $size; @@ -4551,7 +4608,7 @@ class TCPDF { /** * Convert a relative font measure into absolute value. - * @param $s (int) Font measure. + * @param int $s Font measure. * @return float Absolute measure. * @since 5.9.186 (2012-09-13) */ @@ -4561,8 +4618,8 @@ class TCPDF { /** * Returns the glyph bounding box of the specified character in the current font in user units. - * @param $char (int) Input character code. - * @return mixed array(xMin, yMin, xMax, yMax) or FALSE if not defined. + * @param int $char Input character code. + * @return false|array array(xMin, yMin, xMax, yMax) or FALSE if not defined. * @since 5.9.186 (2012-09-13) */ public function getCharBBox($char) { @@ -4580,9 +4637,9 @@ class TCPDF { /** * Return the font descent value - * @param $font (string) font name - * @param $style (string) font style - * @param $size (float) The size (in points) + * @param string $font font name + * @param string $style font style + * @param float $size The size (in points) * @return int font descent * @public * @author Nicola Asuni @@ -4601,9 +4658,9 @@ class TCPDF { /** * Return the font ascent value. - * @param $font (string) font name - * @param $style (string) font style - * @param $size (float) The size (in points) + * @param string $font font name + * @param string $style font style + * @param float $size The size (in points) * @return int font ascent * @public * @author Nicola Asuni @@ -4622,10 +4679,10 @@ class TCPDF { /** * Return true in the character is present in the specified font. - * @param $char (mixed) Character to check (integer value or string) - * @param $font (string) Font name (family name). - * @param $style (string) Font style. - * @return (boolean) true if the char is defined, false otherwise. + * @param mixed $char Character to check (integer value or string) + * @param string $font Font name (family name). + * @param string $style Font style. + * @return bool true if the char is defined, false otherwise. * @public * @since 5.9.153 (2012-03-28) */ @@ -4648,11 +4705,11 @@ class TCPDF { /** * Replace missing font characters on selected font with specified substitutions. - * @param $text (string) Text to process. - * @param $font (string) Font name (family name). - * @param $style (string) Font style. - * @param $subs (array) Array of possible character substitutions. The key is the character to check (integer value) and the value is a single intege value or an array of possible substitutes. - * @return (string) Processed text. + * @param string $text Text to process. + * @param string $font Font name (family name). + * @param string $style Font style. + * @param array $subs Array of possible character substitutions. The key is the character to check (integer value) and the value is a single intege value or an array of possible substitutes. + * @return string Processed text. * @public * @since 5.9.153 (2012-03-28) */ @@ -4689,11 +4746,11 @@ class TCPDF { /** * Defines the default monospaced font. - * @param $font (string) Font name. + * @param string $font Font name. * @public * @since 4.5.025 */ - public function SetDefaultMonospacedFont($font) { + public function setDefaultMonospacedFont($font) { $this->default_monospaced_font = $font; } @@ -4713,14 +4770,14 @@ class TCPDF { /** * Defines the page and position a link points to. - * @param $link (int) The link identifier returned by AddLink() - * @param $y (float) Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page) - * @param $page (int|string) Number of target page; -1 indicates the current page (default value). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. + * @param int $link The link identifier returned by AddLink() + * @param float $y Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page) + * @param int|string $page Number of target page; -1 indicates the current page (default value). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. * @public * @since 1.5 * @see AddLink() */ - public function SetLink($link, $y=0, $page=-1) { + public function setLink($link, $y=0, $page=-1) { $fixed = false; if (!empty($page) AND (substr($page, 0, 1) == '*')) { $page = intval(substr($page, 1)); @@ -4739,12 +4796,12 @@ class TCPDF { /** * Puts a link on a rectangular area of the page. * Text or image links are generally put via Cell(), Write() or Image(), but this method can be useful for instance to define a clickable area inside an image. - * @param $x (float) Abscissa of the upper-left corner of the rectangle - * @param $y (float) Ordinate of the upper-left corner of the rectangle - * @param $w (float) Width of the rectangle - * @param $h (float) Height of the rectangle - * @param $link (mixed) URL or identifier returned by AddLink() - * @param $spaces (int) number of spaces on the text to link + * @param float $x Abscissa of the upper-left corner of the rectangle + * @param float $y Ordinate of the upper-left corner of the rectangle + * @param float $w Width of the rectangle + * @param float $h Height of the rectangle + * @param mixed $link URL or identifier returned by AddLink() + * @param int $spaces number of spaces on the text to link * @public * @since 1.5 * @see AddLink(), Annotation(), Cell(), Write(), Image() @@ -4756,13 +4813,13 @@ class TCPDF { /** * Puts a markup annotation on a rectangular area of the page. * !!!!THE ANNOTATION SUPPORT IS NOT YET FULLY IMPLEMENTED !!!! - * @param $x (float) Abscissa of the upper-left corner of the rectangle - * @param $y (float) Ordinate of the upper-left corner of the rectangle - * @param $w (float) Width of the rectangle - * @param $h (float) Height of the rectangle - * @param $text (string) annotation text or alternate content - * @param $opt (array) array of options (see section 8.4 of PDF reference 1.7). - * @param $spaces (int) number of spaces on the text to link + * @param float $x Abscissa of the upper-left corner of the rectangle + * @param float $y Ordinate of the upper-left corner of the rectangle + * @param float $w Width of the rectangle + * @param float $h Height of the rectangle + * @param string $text annotation text or alternate content + * @param array $opt array of options (see section 8.4 of PDF reference 1.7). + * @param int $spaces number of spaces on the text to link * @public * @since 4.0.018 (2008-08-06) */ @@ -4863,7 +4920,7 @@ class TCPDF { } reset($this->embeddedfiles); foreach ($this->embeddedfiles as $filename => $filedata) { - $data = TCPDF_STATIC::fileGetContents($filedata['file']); + $data = $this->getCachedFileContents($filedata['file']); if ($data !== FALSE) { $rawsize = strlen($data); if ($rawsize > 0) { @@ -4902,31 +4959,31 @@ class TCPDF { /** * Prints a text cell at the specified position. * This method allows to place a string precisely on the page. - * @param $x (float) Abscissa of the cell origin - * @param $y (float) Ordinate of the cell origin - * @param $txt (string) String to print - * @param $fstroke (int) outline size in user units (false = disable) - * @param $fclip (boolean) if true activate clipping mode (you must call StartTransform() before this function and StopTransform() to stop the clipping tranformation). - * @param $ffill (boolean) if true fills the text - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param $ln (int) Indicates where the current position should go after the call. Possible values are:
              • 0: to the right (or left for RTL languages)
              • 1: to the beginning of the next line
              • 2: below
              Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. - * @param $align (string) Allows to center or align the text. Possible values are:
              • L or empty string: left align (default value)
              • C: center
              • R: right align
              • J: justify
              - * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). - * @param $link (mixed) URL or identifier returned by AddLink(). - * @param $stretch (int) font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. - * @param $ignore_min_height (boolean) if true ignore automatic minimum height value. - * @param $calign (string) cell vertical alignment relative to the specified Y value. Possible values are:
              • T : cell top
              • A : font top
              • L : font baseline
              • D : font bottom
              • B : cell bottom
              - * @param $valign (string) text vertical alignment inside the cell. Possible values are:
              • T : top
              • C : center
              • B : bottom
              - * @param $rtloff (boolean) if true uses the page top-left corner as origin of axis for $x and $y initial position. + * @param float $x Abscissa of the cell origin + * @param float $y Ordinate of the cell origin + * @param string $txt String to print + * @param int $fstroke outline size in user units (0 = disable) + * @param boolean $fclip if true activate clipping mode (you must call StartTransform() before this function and StopTransform() to stop the clipping tranformation). + * @param boolean $ffill if true fills the text + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param int $ln Indicates where the current position should go after the call. Possible values are:
              • 0: to the right (or left for RTL languages)
              • 1: to the beginning of the next line
              • 2: below
              Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. + * @param string $align Allows to center or align the text. Possible values are:
              • L or empty string: left align (default value)
              • C: center
              • R: right align
              • J: justify
              + * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). + * @param mixed $link URL or identifier returned by AddLink(). + * @param int $stretch font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. + * @param boolean $ignore_min_height if true ignore automatic minimum height value. + * @param string $calign cell vertical alignment relative to the specified Y value. Possible values are:
              • T : cell top
              • A : font top
              • L : font baseline
              • D : font bottom
              • B : cell bottom
              + * @param string $valign text vertical alignment inside the cell. Possible values are:
              • T : top
              • C : center
              • B : bottom
              + * @param boolean $rtloff if true uses the page top-left corner as origin of axis for $x and $y initial position. * @public * @since 1.0 * @see Cell(), Write(), MultiCell(), WriteHTML(), WriteHTMLCell() */ - public function Text($x, $y, $txt, $fstroke=false, $fclip=false, $ffill=true, $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M', $rtloff=false) { + public function Text($x, $y, $txt, $fstroke=0, $fclip=false, $ffill=true, $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M', $rtloff=false) { $textrendermode = $this->textrendermode; $textstrokewidth = $this->textstrokewidth; $this->setTextRenderingMode($fstroke, $ffill, $fclip); - $this->SetXY($x, $y, $rtloff); + $this->setXY($x, $y, $rtloff); $this->Cell(0, 0, $txt, $border, $ln, $align, $fill, $link, $stretch, $ignore_min_height, $calign, $valign); // restore previous rendering mode $this->textrendermode = $textrendermode; @@ -4937,7 +4994,7 @@ class TCPDF { * Whenever a page break condition is met, the method is called, and the break is issued or not depending on the returned value. * The default implementation returns a value according to the mode selected by SetAutoPageBreak().
              * This method is called automatically and should not be called directly by the application. - * @return boolean + * @return bool * @public * @since 1.4 * @see SetAutoPageBreak() @@ -4962,14 +5019,14 @@ class TCPDF { /** * Add page if needed. - * @param $h (float) Cell height. Default value: 0. - * @param $y (mixed) starting y position, leave empty for current position. - * @param $addpage (boolean) if true add a page, otherwise only return the true/false state - * @return boolean true in case of page break, false otherwise. + * @param float $h Cell height. Default value: 0. + * @param float|null $y starting y position, leave empty for current position. + * @param bool $addpage if true add a page, otherwise only return the true/false state + * @return bool true in case of page break, false otherwise. * @since 3.2.000 (2008-07-01) * @protected */ - protected function checkPageBreak($h=0, $y='', $addpage=true) { + protected function checkPageBreak($h=0, $y=null, $addpage=true) { if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } @@ -5007,18 +5064,18 @@ class TCPDF { /** * Prints a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.
              * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting. - * @param $w (float) Cell width. If 0, the cell extends up to the right margin. - * @param $h (float) Cell height. Default value: 0. - * @param $txt (string) String to print. Default value: empty string. - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param $ln (int) Indicates where the current position should go after the call. Possible values are:
              • 0: to the right (or left for RTL languages)
              • 1: to the beginning of the next line
              • 2: below
              Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. - * @param $align (string) Allows to center or align the text. Possible values are:
              • L or empty string: left align (default value)
              • C: center
              • R: right align
              • J: justify
              - * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). - * @param $link (mixed) URL or identifier returned by AddLink(). - * @param $stretch (int) font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. - * @param $ignore_min_height (boolean) if true ignore automatic minimum height value. - * @param $calign (string) cell vertical alignment relative to the specified Y value. Possible values are:
              • T : cell top
              • C : center
              • B : cell bottom
              • A : font top
              • L : font baseline
              • D : font bottom
              - * @param $valign (string) text vertical alignment inside the cell. Possible values are:
              • T : top
              • C : center
              • B : bottom
              + * @param float $w Cell width. If 0, the cell extends up to the right margin. + * @param float $h Cell height. Default value: 0. + * @param string $txt String to print. Default value: empty string. + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param int $ln Indicates where the current position should go after the call. Possible values are:
              • 0: to the right (or left for RTL languages)
              • 1: to the beginning of the next line
              • 2: below
              Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. + * @param string $align Allows to center or align the text. Possible values are:
              • L or empty string: left align (default value)
              • C: center
              • R: right align
              • J: justify
              + * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). + * @param mixed $link URL or identifier returned by AddLink(). + * @param int $stretch font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. + * @param boolean $ignore_min_height if true ignore automatic minimum height value. + * @param string $calign cell vertical alignment relative to the specified Y value. Possible values are:
              • T : cell top
              • C : center
              • B : cell bottom
              • A : font top
              • L : font baseline
              • D : font bottom
              + * @param string $valign text vertical alignment inside the cell. Possible values are:
              • T : top
              • C : center
              • B : bottom
              * @public * @since 1.0 * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), AddLink(), Ln(), MultiCell(), Write(), SetAutoPageBreak() @@ -5046,9 +5103,9 @@ class TCPDF { // print shadow $this->x += $this->txtshadow['depth_w']; $this->y += $this->txtshadow['depth_h']; - $this->SetFillColorArray($this->txtshadow['color']); - $this->SetTextColorArray($this->txtshadow['color']); - $this->SetDrawColorArray($this->txtshadow['color']); + $this->setFillColorArray($this->txtshadow['color']); + $this->setTextColorArray($this->txtshadow['color']); + $this->setDrawColorArray($this->txtshadow['color']); if ($this->txtshadow['opacity'] != $alpha['CA']) { $this->setAlpha($this->txtshadow['opacity'], $this->txtshadow['blend_mode']); } @@ -5058,9 +5115,9 @@ class TCPDF { //restore data $this->x = $x; $this->y = $y; - $this->SetFillColorArray($bc); - $this->SetTextColorArray($fc); - $this->SetDrawColorArray($sc); + $this->setFillColorArray($bc); + $this->setTextColorArray($fc); + $this->setDrawColorArray($sc); if ($this->txtshadow['opacity'] != $alpha['CA']) { $this->setAlpha($alpha['CA'], $alpha['BM'], $alpha['ca'], $alpha['AIS']); } @@ -5075,18 +5132,18 @@ class TCPDF { /** * Returns the PDF string code to print a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.
              * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting. - * @param $w (float) Cell width. If 0, the cell extends up to the right margin. - * @param $h (float) Cell height. Default value: 0. - * @param $txt (string) String to print. Default value: empty string. - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param $ln (int) Indicates where the current position should go after the call. Possible values are:
              • 0: to the right (or left for RTL languages)
              • 1: to the beginning of the next line
              • 2: below
              Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. - * @param $align (string) Allows to center or align the text. Possible values are:
              • L or empty string: left align (default value)
              • C: center
              • R: right align
              • J: justify
              - * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). - * @param $link (mixed) URL or identifier returned by AddLink(). - * @param $stretch (int) font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. - * @param $ignore_min_height (boolean) if true ignore automatic minimum height value. - * @param $calign (string) cell vertical alignment relative to the specified Y value. Possible values are:
              • T : cell top
              • C : center
              • B : cell bottom
              • A : font top
              • L : font baseline
              • D : font bottom
              - * @param $valign (string) text vertical alignment inside the cell. Possible values are:
              • T : top
              • M : middle
              • B : bottom
              + * @param float $w Cell width. If 0, the cell extends up to the right margin. + * @param float $h Cell height. Default value: 0. + * @param string $txt String to print. Default value: empty string. + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param int $ln Indicates where the current position should go after the call. Possible values are:
              • 0: to the right (or left for RTL languages)
              • 1: to the beginning of the next line
              • 2: below
              Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. + * @param string $align Allows to center or align the text. Possible values are:
              • L or empty string: left align (default value)
              • C: center
              • R: right align
              • J: justify
              + * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). + * @param mixed $link URL or identifier returned by AddLink(). + * @param int $stretch font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. + * @param boolean $ignore_min_height if true ignore automatic minimum height value. + * @param string $calign cell vertical alignment relative to the specified Y value. Possible values are:
              • T : cell top
              • C : center
              • B : cell bottom
              • A : font top
              • L : font baseline
              • D : font bottom
              + * @param string $valign text vertical alignment inside the cell. Possible values are:
              • T : top
              • M : middle
              • B : bottom
              * @return string containing cell code * @protected * @since 1.0 @@ -5554,8 +5611,8 @@ class TCPDF { /** * Replace a char if is defined on the current font. - * @param $oldchar (int) Integer code (unicode) of the character to replace. - * @param $newchar (int) Integer code (unicode) of the new character. + * @param int $oldchar Integer code (unicode) of the character to replace. + * @param int $newchar Integer code (unicode) of the new character. * @return int the replaced char or the old char in case the new char i not defined * @protected * @since 5.9.167 (2012-06-22) @@ -5573,11 +5630,11 @@ class TCPDF { /** * Returns the code to draw the cell border - * @param $x (float) X coordinate. - * @param $y (float) Y coordinate. - * @param $w (float) Cell width. - * @param $h (float) Cell height. - * @param $brd (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param float $x X coordinate. + * @param float $y Y coordinate. + * @param float $w Cell width. + * @param float $h Cell height. + * @param string|array|int $brd Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @return string containing cell border code * @protected * @see SetLineStyle() @@ -5625,7 +5682,7 @@ class TCPDF { if (is_array($style) AND !empty($style)) { // apply border style $prev_style = $this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '; - $s .= $this->SetLineStyle($style, true)."\n"; + $s .= $this->setLineStyle($style, true)."\n"; } switch ($mode) { case 'ext': { @@ -5765,28 +5822,28 @@ class TCPDF { * This method allows printing text with line breaks. * They can be automatic (as soon as the text reaches the right border of the cell) or explicit (via the \n character). As many cells as necessary are output, one below the other.
              * Text can be aligned, centered or justified. The cell block can be framed and the background painted. - * @param $w (float) Width of cells. If 0, they extend up to the right margin of the page. - * @param $h (float) Cell minimum height. The cell extends automatically if needed. - * @param $txt (string) String to print - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param $align (string) Allows to center or align the text. Possible values are:
              • L or empty string: left align
              • C: center
              • R: right align
              • J: justification (default value when $ishtml=false)
              - * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). - * @param $ln (int) Indicates where the current position should go after the call. Possible values are:
              • 0: to the right
              • 1: to the beginning of the next line [DEFAULT]
              • 2: below
              - * @param $x (float) x position in user units - * @param $y (float) y position in user units - * @param $reseth (boolean) if true reset the last cell height (default true). - * @param $stretch (int) font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. - * @param $ishtml (boolean) INTERNAL USE ONLY -- set to true if $txt is HTML content (default = false). Never set this parameter to true, use instead writeHTMLCell() or writeHTML() methods. - * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width. - * @param $maxh (float) maximum height. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. This feature works only when $ishtml=false. - * @param $valign (string) Vertical alignment of text (requires $maxh = $h > 0). Possible values are:
              • T: TOP
              • M: middle
              • B: bottom
              . This feature works only when $ishtml=false and the cell must fit in a single page. - * @param $fitcell (boolean) if true attempt to fit all the text within the cell by reducing the font size (do not work in HTML mode). $maxh must be greater than 0 and equal to $h. + * @param float $w Width of cells. If 0, they extend up to the right margin of the page. + * @param float $h Cell minimum height. The cell extends automatically if needed. + * @param string $txt String to print + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param string $align Allows to center or align the text. Possible values are:
              • L or empty string: left align
              • C: center
              • R: right align
              • J: justification (default value when $ishtml=false)
              + * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). + * @param int $ln Indicates where the current position should go after the call. Possible values are:
              • 0: to the right
              • 1: to the beginning of the next line [DEFAULT]
              • 2: below
              + * @param float|null $x x position in user units + * @param float|null $y y position in user units + * @param boolean $reseth if true reset the last cell height (default true). + * @param int $stretch font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. + * @param boolean $ishtml INTERNAL USE ONLY -- set to true if $txt is HTML content (default = false). Never set this parameter to true, use instead writeHTMLCell() or writeHTML() methods. + * @param boolean $autopadding if true, uses internal padding and automatically adjust it to account for line width. + * @param float $maxh maximum height. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. This feature works only when $ishtml=false. + * @param string $valign Vertical alignment of text (requires $maxh = $h > 0). Possible values are:
              • T: TOP
              • M: middle
              • B: bottom
              . This feature works only when $ishtml=false and the cell must fit in a single page. + * @param boolean $fitcell if true attempt to fit all the text within the cell by reducing the font size (do not work in HTML mode). $maxh must be greater than 0 and equal to $h. * @return int Return the number of cells or 1 for html mode. * @public * @since 1.3 * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), Cell(), Write(), SetAutoPageBreak() */ - public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false, $ln=1, $x='', $y='', $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0, $valign='T', $fitcell=false) { + public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false, $ln=1, $x=null, $y=null, $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0, $valign='T', $fitcell=false) { $prev_cell_margin = $this->cell_margin; $prev_cell_padding = $this->cell_padding; // adjust internal padding @@ -5801,7 +5858,7 @@ class TCPDF { $this->resetLastH(); } if (!TCPDF_STATIC::empty_string($y)) { - $this->SetY($y); // set y in order to convert negative y values to positive ones + $this->setY($y); // set y in order to convert negative y values to positive ones } $y = $this->GetY(); $resth = 0; @@ -5816,7 +5873,7 @@ class TCPDF { // get current column $startcolumn = $this->current_column; if (!TCPDF_STATIC::empty_string($x)) { - $this->SetX($x); + $this->setX($x); } else { $x = $this->GetX(); } @@ -5877,7 +5934,7 @@ class TCPDF { $maxit = (2 * min(100, max(10, intval($fmax)))); // max number of iterations while ($maxit >= 0) { $fmid = (($fmax + $fmin) / 2); - $this->SetFontSize($fmid, false); + $this->setFontSize($fmid, false); $this->resetLastH(); $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border); $diff = ($maxh - $text_height); @@ -5893,11 +5950,11 @@ class TCPDF { } if ($maxit < 0) { // premature exit, we get the minimum font value to fit the cell - $this->SetFontSize($fmin); + $this->setFontSize($fmin); $this->resetLastH(); $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border); } else { - $this->SetFontSize($fmid); + $this->setFontSize($fmid); $this->resetLastH(); } } @@ -5914,7 +5971,7 @@ class TCPDF { $nl = $this->Write($this->lasth, $txt, '', 0, $align, true, $stretch, false, true, $maxh, 0, $mc_margin); if ($fitcell) { // restore font size - $this->SetFontSize($prev_FontSizePt); + $this->setFontSize($prev_FontSizePt); } } if ($autopadding) { @@ -5961,7 +6018,7 @@ class TCPDF { $this->setPage($page); if ($this->num_columns < 2) { // single-column mode - $this->SetX($x); + $this->setX($x); $this->y = $this->tMargin; } // account for margin changes @@ -6123,15 +6180,15 @@ class TCPDF { } if ($ln > 0) { //Go to the beginning of the next line - $this->SetY($currentY + $mc_margin['B']); + $this->setY($currentY + $mc_margin['B']); if ($ln == 2) { - $this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']); + $this->setX($x + $w + $mc_margin['L'] + $mc_margin['R']); } } else { // go left or right by case $this->setPage($startpage); $this->y = $y; - $this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']); + $this->setX($x + $w + $mc_margin['L'] + $mc_margin['R']); } $this->setContentMark(); $this->cell_padding = $prev_cell_padding; @@ -6143,18 +6200,18 @@ class TCPDF { /** * This method return the estimated number of lines for print a simple text string using Multicell() method. - * @param $txt (string) String for calculating his height - * @param $w (float) Width of cells. If 0, they extend up to the right margin of the page. - * @param $reseth (boolean) if true reset the last cell height (default false). - * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width (default true). - * @param $cellpadding (float) Internal cell padding, if empty uses default cell padding. - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param string $txt String for calculating his height + * @param float $w Width of cells. If 0, they extend up to the right margin of the page. + * @param boolean $reseth if true reset the last cell height (default false). + * @param boolean $autopadding if true, uses internal padding and automatically adjust it to account for line width (default true). + * @param array|null $cellpadding Internal cell padding, if empty uses default cell padding. + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @return float Return the minimal height needed for multicell method for printing the $txt param. * @author Alexander Escalona Fern\E1ndez, Nicola Asuni * @public * @since 4.5.011 */ - public function getNumLines($txt, $w=0, $reseth=false, $autopadding=true, $cellpadding='', $border=0) { + public function getNumLines($txt, $w=0, $reseth=false, $autopadding=true, $cellpadding=null, $border=0) { if ($txt === NULL) { return 0; } @@ -6237,7 +6294,7 @@ class TCPDF { * $start_page = $pdf->getPage(); * // call your printing functions with your parameters * // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * $pdf->MultiCell($w=0, $h=0, $txt, $border=1, $align='L', $fill=false, $ln=1, $x='', $y='', $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0); + * $pdf->MultiCell($w=0, $h=0, $txt, $border=1, $align='L', $fill=false, $ln=1, $x=null, $y=null, $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0); * // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * // get the new Y * $end_y = $pdf->GetY(); @@ -6263,17 +6320,17 @@ class TCPDF { * // restore previous object * $pdf = $pdf->rollbackTransaction(); * - * @param $w (float) Width of cells. If 0, they extend up to the right margin of the page. - * @param $txt (string) String for calculating his height - * @param $reseth (boolean) if true reset the last cell height (default false). - * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width (default true). - * @param $cellpadding (float) Internal cell padding, if empty uses default cell padding. - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param float $w Width of cells. If 0, they extend up to the right margin of the page. + * @param string $txt String for calculating his height + * @param boolean $reseth if true reset the last cell height (default false). + * @param boolean $autopadding if true, uses internal padding and automatically adjust it to account for line width (default true). + * @param array|null $cellpadding Internal cell padding, if empty uses default cell padding. + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @return float Return the minimal height needed for multicell method for printing the $txt param. * @author Nicola Asuni, Alexander Escalona Fern\E1ndez * @public */ - public function getStringHeight($w, $txt, $reseth=false, $autopadding=true, $cellpadding='', $border=0) { + public function getStringHeight($w, $txt, $reseth=false, $autopadding=true, $cellpadding=null, $border=0) { // adjust internal padding $prev_cell_padding = $this->cell_padding; $prev_lasth = $this->lasth; @@ -6290,30 +6347,30 @@ class TCPDF { /** * This method prints text from the current position.
              - * @param $h (float) Line height - * @param $txt (string) String to print - * @param $link (mixed) URL or identifier returned by AddLink() - * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). - * @param $align (string) Allows to center or align the text. Possible values are:
              • L or empty string: left align (default value)
              • C: center
              • R: right align
              • J: justify
              - * @param $ln (boolean) if true set cursor at the bottom of the line, otherwise set cursor at the top of the line. - * @param $stretch (int) font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. - * @param $firstline (boolean) if true prints only the first line and return the remaining string. - * @param $firstblock (boolean) if true the string is the starting of a line. - * @param $maxh (float) maximum height. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. - * @param $wadj (float) first line width will be reduced by this amount (used in HTML mode). - * @param $margin (array) margin array of the parent container + * @param float $h Line height + * @param string $txt String to print + * @param mixed $link URL or identifier returned by AddLink() + * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). + * @param string $align Allows to center or align the text. Possible values are:
              • L or empty string: left align (default value)
              • C: center
              • R: right align
              • J: justify
              + * @param boolean $ln if true set cursor at the bottom of the line, otherwise set cursor at the top of the line. + * @param int $stretch font stretch mode:
              • 0 = disabled
              • 1 = horizontal scaling only if text is larger than cell width
              • 2 = forced horizontal scaling to fit cell width
              • 3 = character spacing only if text is larger than cell width
              • 4 = forced character spacing to fit cell width
              General font stretching and scaling values will be preserved when possible. + * @param boolean $firstline if true prints only the first line and return the remaining string. + * @param boolean $firstblock if true the string is the starting of a line. + * @param float $maxh maximum height. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. + * @param float $wadj first line width will be reduced by this amount (used in HTML mode). + * @param array|null $margin margin array of the parent container * @return mixed Return the number of cells or the remaining string if $firstline = true. * @public * @since 1.5 */ - public function Write($h, $txt, $link='', $fill=false, $align='', $ln=false, $stretch=0, $firstline=false, $firstblock=false, $maxh=0, $wadj=0, $margin='') { + public function Write($h, $txt, $link='', $fill=false, $align='', $ln=false, $stretch=0, $firstline=false, $firstblock=false, $maxh=0, $wadj=0, $margin=null) { // check page for no-write regions and adapt page margins if necessary list($this->x, $this->y) = $this->checkPageRegions($h, $this->x, $this->y); if (strlen($txt) == 0) { // fix empty text $txt = ' '; } - if ($margin === '') { + if (!is_array($margin)) { // set default margins $margin = $this->cell_margin; } @@ -6415,7 +6472,7 @@ class TCPDF { $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { - $this->SetCellPadding(0); + $this->setCellPadding(0); } } if ($firstblock AND $this->isRTLTextDir()) { @@ -6489,7 +6546,7 @@ class TCPDF { // *** very slow *** $l = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(array_slice($chars, $j, ($i - $j)), '', $this->tmprtl, $this->isunicode, $this->CurrentFont)); } else { - $l += $this->GetCharWidth($c); + $l += $this->GetCharWidth($c, ($i+1 < $nb)); } if (($l > $wmax) OR (($c == 173) AND (($l + $tmp_shy_replacement_width) >= $wmax))) { if (($c == 173) AND (($l + $tmp_shy_replacement_width) > $wmax)) { @@ -6526,7 +6583,7 @@ class TCPDF { $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { - $this->SetCellPadding(0); + $this->setCellPadding(0); } } if ($firstblock AND $this->isRTLTextDir()) { @@ -6570,7 +6627,7 @@ class TCPDF { $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { - $this->SetCellPadding(0); + $this->setCellPadding(0); } } if ($firstblock AND $this->isRTLTextDir()) { @@ -6618,7 +6675,7 @@ class TCPDF { $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { - $this->SetCellPadding(0); + $this->setCellPadding(0); } } // print the line @@ -6671,13 +6728,10 @@ class TCPDF { switch ($align) { case 'J': case 'C': { - $w = $w; break; } case 'L': { - if ($this->rtl) { - $w = $w; - } else { + if (!$this->rtl) { $w = $l; } break; @@ -6685,8 +6739,6 @@ class TCPDF { case 'R': { if ($this->rtl) { $w = $l; - } else { - $w = $w; } break; } @@ -6712,7 +6764,7 @@ class TCPDF { $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { - $this->SetCellPadding(0); + $this->setCellPadding(0); } } if ($firstblock AND $this->isRTLTextDir()) { @@ -6734,7 +6786,7 @@ class TCPDF { /** * Returns the remaining width between the current position and margins. - * @return int Return the remaining width + * @return float Return the remaining width * @protected */ protected function getRemainingWidth() { @@ -6748,12 +6800,12 @@ class TCPDF { /** * Set the block dimensions accounting for page breaks and page/column fitting - * @param $w (float) width - * @param $h (float) height - * @param $x (float) X coordinate - * @param $y (float) Y coodiante - * @param $fitonpage (boolean) if true the block is resized to not exceed page dimensions. - * @return array($w, $h, $x, $y) + * @param float $w width + * @param float $h height + * @param float $x X coordinate + * @param float $y Y coodiante + * @param boolean $fitonpage if true the block is resized to not exceed page dimensions. + * @return array array($w, $h, $x, $y) * @protected * @since 5.5.009 (2010-07-05) */ @@ -6829,43 +6881,49 @@ class TCPDF { * The format can be specified explicitly or inferred from the file extension.
              * It is possible to put a link on the image.
              * Remark: if an image is used several times, only one copy will be embedded in the file.
              - * @param $file (string) Name of the file containing the image or a '@' character followed by the image data string. To link an image without embedding it on the document, set an asterisk character before the URL (i.e.: '*http://www.example.com/image.jpg'). - * @param $x (float) Abscissa of the upper-left corner (LTR) or upper-right corner (RTL). - * @param $y (float) Ordinate of the upper-left corner (LTR) or upper-right corner (RTL). - * @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param $type (string) Image format. Possible values are (case insensitive): JPEG and PNG (whitout GD library) and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM;. If not specified, the type is inferred from the file extension. - * @param $link (mixed) URL or identifier returned by AddLink(). - * @param $align (string) Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
              • T: top-right for LTR or top-left for RTL
              • M: middle-right for LTR or middle-left for RTL
              • B: bottom-right for LTR or bottom-left for RTL
              • N: next line
              - * @param $resize (mixed) If true resize (reduce) the image to fit $w and $h (requires GD or ImageMagick library); if false do not resize; if 2 force resize in all cases (upscaling and downscaling). - * @param $dpi (int) dot-per-inch resolution used on resize - * @param $palign (string) Allows to center or align the image on the current line. Possible values are:
              • L : left align
              • C : center
              • R : right align
              • '' : empty string : left for LTR or right for RTL
              - * @param $ismask (boolean) true if this image is a mask, false otherwise - * @param $imgmask (mixed) image object returned by this function or false - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param $fitbox (mixed) If not false scale image dimensions proportionally to fit within the ($w, $h) box. $fitbox can be true or a 2 characters string indicating the image alignment inside the box. The first character indicate the horizontal alignment (L = left, C = center, R = right) the second character indicate the vertical algnment (T = top, M = middle, B = bottom). - * @param $hidden (boolean) If true do not display the image. - * @param $fitonpage (boolean) If true the image is resized to not exceed page dimensions. - * @param $alt (boolean) If true the image will be added as alternative and not directly printed (the ID of the image will be returned). - * @param $altimgs (array) Array of alternate images IDs. Each alternative image must be an array with two values: an integer representing the image ID (the value returned by the Image method) and a boolean value to indicate if the image is the default for printing. - * @return image information + * @param string $file Name of the file containing the image or a '@' character followed by the image data string. To link an image without embedding it on the document, set an asterisk character before the URL (i.e.: '*http://www.example.com/image.jpg'). + * @param float|null $x Abscissa of the upper-left corner (LTR) or upper-right corner (RTL). + * @param float|null $y Ordinate of the upper-left corner (LTR) or upper-right corner (RTL). + * @param float $w Width of the image in the page. If not specified or equal to zero, it is automatically calculated. + * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated. + * @param string $type Image format. Possible values are (case insensitive): JPEG and PNG (whitout GD library) and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM;. If not specified, the type is inferred from the file extension. + * @param mixed $link URL or identifier returned by AddLink(). + * @param string $align Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
              • T: top-right for LTR or top-left for RTL
              • M: middle-right for LTR or middle-left for RTL
              • B: bottom-right for LTR or bottom-left for RTL
              • N: next line
              + * @param mixed $resize If true resize (reduce) the image to fit $w and $h (requires GD or ImageMagick library); if false do not resize; if 2 force resize in all cases (upscaling and downscaling). + * @param int $dpi dot-per-inch resolution used on resize + * @param string $palign Allows to center or align the image on the current line. Possible values are:
              • L : left align
              • C : center
              • R : right align
              • '' : empty string : left for LTR or right for RTL
              + * @param boolean $ismask true if this image is a mask, false otherwise + * @param mixed $imgmask image object returned by this function or false + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param mixed $fitbox If not false scale image dimensions proportionally to fit within the ($w, $h) box. $fitbox can be true or a 2 characters string indicating the image alignment inside the box. The first character indicate the horizontal alignment (L = left, C = center, R = right) the second character indicate the vertical algnment (T = top, M = middle, B = bottom). + * @param boolean $hidden If true do not display the image. + * @param boolean $fitonpage If true the image is resized to not exceed page dimensions. + * @param boolean $alt If true the image will be added as alternative and not directly printed (the ID of the image will be returned). + * @param array $altimgs Array of alternate images IDs. Each alternative image must be an array with two values: an integer representing the image ID (the value returned by the Image method) and a boolean value to indicate if the image is the default for printing. + * @return mixed|false image information * @public * @since 1.1 */ - public function Image($file, $x='', $y='', $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0, $fitbox=false, $hidden=false, $fitonpage=false, $alt=false, $altimgs=array()) { + public function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0, $fitbox=false, $hidden=false, $fitonpage=false, $alt=false, $altimgs=array()) { if ($this->state != 2) { - return; + return false; } - if (strcmp($x, '') === 0) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if (strcmp($y, '') === 0) { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); $exurl = ''; // external streams $imsize = FALSE; + + // Make sure the file variable is not empty or null because accessing $file[0] later + // results in error when running PHP 7.4 + if (empty($file)) { + return false; + } // check if we are passing an image as file or string if ($file[0] === '@') { // image from string @@ -6877,18 +6935,14 @@ class TCPDF { $exurl = $file; } // check if file exist and it is valid - if (!@TCPDF_STATIC::file_exists($file)) { + if (!@$this->fileExists($file)) { return false; } - if (($imsize = @getimagesize($file)) === FALSE) { - if (in_array($file, $this->imagekeys)) { - // get existing image data - $info = $this->getImageBuffer($file); - $imsize = array($info['w'], $info['h']); - } elseif (strpos($file, '__tcpdf_'.$this->file_id.'_img') === FALSE) { - $imgdata = TCPDF_STATIC::fileGetContents($file); - } - } + if (false !== $info = $this->getImageBuffer($file)) { + $imsize = array($info['w'], $info['h']); + } elseif (($imsize = @getimagesize($file)) === FALSE && strpos($file, '__tcpdf_'.$this->file_id.'_img') === FALSE){ + $imgdata = $this->getCachedFileContents($file); + } } if (!empty($imgdata)) { // copy image to cache @@ -7093,7 +7147,7 @@ class TCPDF { $svgimg = substr($file, 1); } else { // get SVG file content - $svgimg = TCPDF_STATIC::fileGetContents($file); + $svgimg = $this->getCachedFileContents($file); } if ($svgimg !== FALSE) { // get width and height @@ -7146,7 +7200,7 @@ class TCPDF { } if ($info === false) { // unable to process image - return; + return false; } TCPDF_STATIC::set_mqr($mqr); if ($ismask) { @@ -7221,7 +7275,7 @@ class TCPDF { break; } case 'N': { - $this->SetY($this->img_rb_y); + $this->setY($this->img_rb_y); break; } default:{ @@ -7238,20 +7292,20 @@ class TCPDF { /** * Extract info from a PNG image with alpha channel using the Imagick or GD library. - * @param $file (string) Name of the file containing the image. - * @param $x (float) Abscissa of the upper-left corner. - * @param $y (float) Ordinate of the upper-left corner. - * @param $wpx (float) Original width of the image in pixels. - * @param $hpx (float) original height of the image in pixels. - * @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param $type (string) Image format. Possible values are (case insensitive): JPEG and PNG (whitout GD library) and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM;. If not specified, the type is inferred from the file extension. - * @param $link (mixed) URL or identifier returned by AddLink(). - * @param $align (string) Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
              • T: top-right for LTR or top-left for RTL
              • M: middle-right for LTR or middle-left for RTL
              • B: bottom-right for LTR or bottom-left for RTL
              • N: next line
              - * @param $resize (boolean) If true resize (reduce) the image to fit $w and $h (requires GD library). - * @param $dpi (int) dot-per-inch resolution used on resize - * @param $palign (string) Allows to center or align the image on the current line. Possible values are:
              • L : left align
              • C : center
              • R : right align
              • '' : empty string : left for LTR or right for RTL
              - * @param $filehash (string) File hash used to build unique file names. + * @param string $file Name of the file containing the image. + * @param float $x Abscissa of the upper-left corner. + * @param float $y Ordinate of the upper-left corner. + * @param float $wpx Original width of the image in pixels. + * @param float $hpx original height of the image in pixels. + * @param float $w Width of the image in the page. If not specified or equal to zero, it is automatically calculated. + * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated. + * @param string $type Image format. Possible values are (case insensitive): JPEG and PNG (whitout GD library) and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM;. If not specified, the type is inferred from the file extension. + * @param mixed $link URL or identifier returned by AddLink(). + * @param string $align Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
              • T: top-right for LTR or top-left for RTL
              • M: middle-right for LTR or middle-left for RTL
              • B: bottom-right for LTR or bottom-left for RTL
              • N: next line
              + * @param boolean $resize If true resize (reduce) the image to fit $w and $h (requires GD library). + * @param int $dpi dot-per-inch resolution used on resize + * @param string $palign Allows to center or align the image on the current line. Possible values are:
              • L : left align
              • C : center
              • R : right align
              • '' : empty string : left for LTR or right for RTL
              + * @param string $filehash File hash used to build unique file names. * @author Nicola Asuni * @protected * @since 4.3.007 (2008-12-04) @@ -7315,7 +7369,7 @@ class TCPDF { $color = imagecolorat($img, $xpx, $ypx); // get and correct gamma color $alpha = $this->getGDgamma($img, $color); - imagesetpixel($imgalpha, $xpx, $ypx, $alpha); + imagesetpixel($imgalpha, (int) $xpx, (int) $ypx, (int) $alpha); } } imagepng($imgalpha, $tempfile_alpha); @@ -7346,8 +7400,8 @@ class TCPDF { /** * Get the GD-corrected PNG gamma value from alpha color - * @param $img (int) GD image Resource ID. - * @param $c (int) alpha color + * @param resource $img GD image Resource ID. + * @param int $c alpha color * @protected * @since 4.3.007 (2008-12-04) */ @@ -7355,9 +7409,9 @@ class TCPDF { if (!isset($this->gdgammacache['#'.$c])) { $colors = imagecolorsforindex($img, $c); // GD alpha is only 7 bit (0 -> 127) - $this->gdgammacache['#'.$c] = (((127 - $colors['alpha']) / 127) * 255); + $this->gdgammacache['#'.$c] = (int) (((127 - $colors['alpha']) / 127) * 255); // correct gamma - $this->gdgammacache['#'.$c] = (pow(($this->gdgammacache['#'.$c] / 255), 2.2) * 255); + $this->gdgammacache['#'.$c] = (int) (pow(($this->gdgammacache['#'.$c] / 255), 2.2) * 255); // store the latest values on cache to improve performances if (count($this->gdgammacache) > 8) { // remove one element from the cache array @@ -7370,13 +7424,13 @@ class TCPDF { /** * Performs a line break. * The current abscissa goes back to the left margin and the ordinate increases by the amount passed in parameter. - * @param $h (float) The height of the break. By default, the value equals the height of the last printed cell. - * @param $cell (boolean) if true add the current left (or right o for RTL) padding to the X coordinate + * @param float|null $h The height of the break. By default, the value equals the height of the last printed cell. + * @param boolean $cell if true add the current left (or right o for RTL) padding to the X coordinate * @public * @since 1.0 * @see Cell() */ - public function Ln($h='', $cell=false) { + public function Ln($h=null, $cell=false) { if (($this->num_columns > 1) AND ($this->y == $this->columns[$this->current_column]['y']) AND isset($this->columns[$this->current_column]['x']) AND ($this->x == $this->columns[$this->current_column]['x'])) { // revove vertical space from the top of the column return; @@ -7395,7 +7449,7 @@ class TCPDF { } else { $this->x = $this->lMargin + $cellpadding; } - if (is_string($h)) { + if (TCPDF_STATIC::empty_string($h)) { $h = $this->lasth; } $this->y += $h; @@ -7444,13 +7498,13 @@ class TCPDF { /** * Defines the abscissa of the current position. * If the passed value is negative, it is relative to the right of the page (or left if language is RTL). - * @param $x (float) The value of the abscissa in user units. - * @param $rtloff (boolean) if true always uses the page top-left corner as origin of axis. + * @param float $x The value of the abscissa in user units. + * @param boolean $rtloff if true always uses the page top-left corner as origin of axis. * @public * @since 1.2 * @see GetX(), GetY(), SetY(), SetXY() */ - public function SetX($x, $rtloff=false) { + public function setX($x, $rtloff=false) { $x = floatval($x); if (!$rtloff AND $this->rtl) { if ($x >= 0) { @@ -7476,14 +7530,14 @@ class TCPDF { /** * Moves the current abscissa back to the left margin and sets the ordinate. * If the passed value is negative, it is relative to the bottom of the page. - * @param $y (float) The value of the ordinate in user units. - * @param $resetx (bool) if true (default) reset the X position. - * @param $rtloff (boolean) if true always uses the page top-left corner as origin of axis. + * @param float $y The value of the ordinate in user units. + * @param bool $resetx if true (default) reset the X position. + * @param boolean $rtloff if true always uses the page top-left corner as origin of axis. * @public * @since 1.0 * @see GetX(), GetY(), SetY(), SetXY() */ - public function SetY($y, $resetx=true, $rtloff=false) { + public function setY($y, $resetx=true, $rtloff=false) { $y = floatval($y); if ($resetx) { //reset x @@ -7509,59 +7563,59 @@ class TCPDF { /** * Defines the abscissa and ordinate of the current position. * If the passed values are negative, they are relative respectively to the right and bottom of the page. - * @param $x (float) The value of the abscissa. - * @param $y (float) The value of the ordinate. - * @param $rtloff (boolean) if true always uses the page top-left corner as origin of axis. + * @param float $x The value of the abscissa. + * @param float $y The value of the ordinate. + * @param boolean $rtloff if true always uses the page top-left corner as origin of axis. * @public * @since 1.2 * @see SetX(), SetY() */ - public function SetXY($x, $y, $rtloff=false) { - $this->SetY($y, false, $rtloff); - $this->SetX($x, $rtloff); + public function setXY($x, $y, $rtloff=false) { + $this->setY($y, false, $rtloff); + $this->setX($x, $rtloff); } /** * Set the absolute X coordinate of the current pointer. - * @param $x (float) The value of the abscissa in user units. + * @param float $x The value of the abscissa in user units. * @public * @since 5.9.186 (2012-09-13) * @see setAbsX(), setAbsY(), SetAbsXY() */ - public function SetAbsX($x) { + public function setAbsX($x) { $this->x = floatval($x); } /** * Set the absolute Y coordinate of the current pointer. - * @param $y (float) (float) The value of the ordinate in user units. + * @param float $y (float) The value of the ordinate in user units. * @public * @since 5.9.186 (2012-09-13) * @see setAbsX(), setAbsY(), SetAbsXY() */ - public function SetAbsY($y) { + public function setAbsY($y) { $this->y = floatval($y); } /** * Set the absolute X and Y coordinates of the current pointer. - * @param $x (float) The value of the abscissa in user units. - * @param $y (float) (float) The value of the ordinate in user units. + * @param float $x The value of the abscissa in user units. + * @param float $y (float) The value of the ordinate in user units. * @public * @since 5.9.186 (2012-09-13) * @see setAbsX(), setAbsY(), SetAbsXY() */ - public function SetAbsXY($x, $y) { - $this->SetAbsX($x); - $this->SetAbsY($y); + public function setAbsXY($x, $y) { + $this->setAbsX($x); + $this->setAbsY($y); } /** * Send the document to a given destination: string, local file or browser. * In the last case, the plug-in may be used (if present) or a download ("Save as" dialog box) may be forced.
              * The method first calls Close() if necessary to terminate the document. - * @param $name (string) The name of the file when saved. Note that special characters are removed and blanks characters are replaced with the underscore character. - * @param $dest (string) Destination where to send the document. It can take one of the following values:
              • I: send the file inline to the browser (default). The plug-in is used if available. The name given by name is used when one selects the "Save as" option on the link generating the PDF.
              • D: send to the browser and force a file download with the name given by name.
              • F: save to a local server file with the name given by name.
              • S: return the document as a string (name is ignored).
              • FI: equivalent to F + I option
              • FD: equivalent to F + D option
              • E: return the document as base64 mime multi-part email attachment (RFC 2045)
              + * @param string $name The name of the file when saved. Note that special characters are removed and blanks characters are replaced with the underscore character. + * @param string $dest Destination where to send the document. It can take one of the following values:
              • I: send the file inline to the browser (default). The plug-in is used if available. The name given by name is used when one selects the "Save as" option on the link generating the PDF.
              • D: send to the browser and force a file download with the name given by name.
              • F: save to a local server file with the name given by name.
              • S: return the document as a string (name is ignored).
              • FI: equivalent to F + I option
              • FD: equivalent to F + D option
              • E: return the document as base64 mime multi-part email attachment (RFC 2045)
              * @return string * @public * @since 1.0 @@ -7761,20 +7815,16 @@ class TCPDF { protected static $cleaned_ids = array(); /** * Unset all class variables except the following critical variables. - * @param $destroyall (boolean) if true destroys all class variables, otherwise preserves critical variables. - * @param $preserve_objcopy (boolean) if true preserves the objcopy variable + * @param boolean $destroyall if true destroys all class variables, otherwise preserves critical variables. + * @param boolean $preserve_objcopy if true preserves the objcopy variable * @public * @since 4.5.016 (2009-02-24) */ public function _destroy($destroyall=false, $preserve_objcopy=false) { - // restore internal encoding - if (isset($this->internal_encoding) AND !empty($this->internal_encoding)) { - mb_internal_encoding($this->internal_encoding); - } if (isset(self::$cleaned_ids[$this->file_id])) { $destroyall = false; } - if ($destroyall AND !$preserve_objcopy) { + if ($destroyall AND !$preserve_objcopy && isset($this->file_id)) { self::$cleaned_ids[$this->file_id] = true; // remove all temporary files if ($handle = @opendir(K_PATH_CACHE)) { @@ -7787,7 +7837,7 @@ class TCPDF { } if (isset($this->imagekeys)) { foreach($this->imagekeys as $file) { - if (strpos($file, K_PATH_CACHE) === 0) { + if (strpos($file, K_PATH_CACHE) === 0 && TCPDF_STATIC::file_exists($file)) { @unlink($file); } } @@ -7795,7 +7845,6 @@ class TCPDF { } $preserve = array( 'file_id', - 'internal_encoding', 'state', 'bufferlen', 'buffer', @@ -7834,7 +7883,7 @@ class TCPDF { /** * Return an array containing variations for the basic page number alias. - * @param $a (string) Base alias. + * @param string $a Base alias. * @return array of page number aliases * @protected */ @@ -7871,10 +7920,10 @@ class TCPDF { /** * Replace right shift page number aliases with spaces to correct right alignment. * This works perfectly only when using monospaced fonts. - * @param $page (string) Page content. - * @param $aliases (array) Array of page aliases. - * @param $diff (int) initial difference to add. - * @return replaced page content. + * @param string $page Page content. + * @param array $aliases Array of page aliases. + * @param int $diff initial difference to add. + * @return string replaced page content. * @protected */ protected function replaceRightShiftPageNumAliases($page, $aliases, $diff) { @@ -7909,7 +7958,7 @@ class TCPDF { /** * Set page boxes to be included on page descriptions. - * @param $boxes (array) Array of page boxes to set on document: ('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox'). + * @param array $boxes Array of page boxes to set on document: ('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox'). * @protected */ protected function setPageBoxTypes($boxes) { @@ -8024,7 +8073,7 @@ class TCPDF { } $out .= ' /Contents '.($this->n + 1).' 0 R'; $out .= ' /Rotate '.$this->pagedim[$n]['Rotate']; - if (!$this->pdfa_mode) { + if (!$this->pdfa_mode || $this->pdfa_version >= 2) { $out .= ' /Group << /Type /Group /S /Transparency /CS /DeviceRGB >>'; } if (isset($this->pagedim[$n]['trans']) AND !empty($this->pagedim[$n]['trans'])) { @@ -8081,7 +8130,7 @@ class TCPDF { /** * Get references to page annotations. - * @param $n (int) page number + * @param int $n page number * @return string * @protected * @author Nicola Asuni @@ -8379,8 +8428,13 @@ class TCPDF { } else { $annots .= ' /Name /Note'; } + $hasStateModel = isset($pl['opt']['statemodel']); + $hasState = isset($pl['opt']['state']); $statemodels = array('Marked', 'Review'); - if (isset($pl['opt']['statemodel']) AND in_array($pl['opt']['statemodel'], $statemodels)) { + if (!$hasStateModel && !$hasState) { + break; + } + if ($hasStateModel AND in_array($pl['opt']['statemodel'], $statemodels)) { $annots .= ' /StateModel /'.$pl['opt']['statemodel']; } else { $pl['opt']['statemodel'] = 'Marked'; @@ -8391,7 +8445,7 @@ class TCPDF { } else { $states = array('Accepted', 'Rejected', 'Cancelled', 'Completed', 'None'); } - if (isset($pl['opt']['state']) AND in_array($pl['opt']['state'], $states)) { + if ($hasState AND in_array($pl['opt']['state'], $states)) { $annots .= ' /State /'.$pl['opt']['state']; } else { if ($pl['opt']['statemodel'] == 'Marked') { @@ -8406,7 +8460,7 @@ class TCPDF { if (is_string($pl['txt']) && !empty($pl['txt'])) { if ($pl['txt'][0] == '#') { // internal destination - $annots .= ' /A <>'; + $annots .= ' /A <>'; } elseif ($pl['txt'][0] == '%') { // embedded PDF file $filename = basename(substr($pl['txt'], 1)); @@ -8769,9 +8823,9 @@ class TCPDF { /** * Put appearance streams XObject used to define annotation's appearance states. - * @param $w (int) annotation width - * @param $h (int) annotation height - * @param $stream (string) appearance stream + * @param int $w annotation width + * @param int $h annotation height + * @param string $stream appearance stream * @return int object ID * @protected * @since 4.8.001 (2009-09-09) @@ -8953,7 +9007,7 @@ class TCPDF { /** * Adds unicode fonts.
              * Based on PDF Reference 1.3 (section 5) - * @param $font (array) font data + * @param array $font font data * @protected * @author Nicola Asuni * @since 1.52.0.TC005 (2005-01-05) @@ -9057,7 +9111,7 @@ class TCPDF { /** * Output CID-0 fonts. * A Type 0 CIDFont contains glyph descriptions based on the Adobe Type 1 font format - * @param $font (array) font data + * @param array $font font data * @protected * @author Andrew Whitehead, Nicola Asuni, Yukihiro Nakadaira * @since 3.2.000 (2008-06-23) @@ -9278,7 +9332,7 @@ class TCPDF { $out .= ' /Matrix [1 0 0 1 0 0]'; $out .= ' /Resources <<'; $out .= ' /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'; - if (!$this->pdfa_mode) { + if (!$this->pdfa_mode || $this->pdfa_version >= 2) { // transparency if (isset($data['extgstates']) AND !empty($data['extgstates'])) { $out .= ' /ExtGState <<'; @@ -9416,7 +9470,7 @@ class TCPDF { } $out .= ' >>'; } - if (!$this->pdfa_mode) { + if (!$this->pdfa_mode || $this->pdfa_version >= 2) { // transparency if (isset($this->extgstates) AND !empty($this->extgstates)) { $out .= ' /ExtGState <<'; @@ -9530,7 +9584,7 @@ class TCPDF { /** * Set additional XMP data to be added on the default XMP data just before the end of "x:xmpmeta" tag. * IMPORTANT: This data is added as-is without controls, so you have to validate your data before using this method! - * @param $xmp (string) Custom XMP data. + * @param string $xmp Custom XMP data. * @since 5.9.128 (2011-10-06) * @public */ @@ -9541,7 +9595,7 @@ class TCPDF { /** * Set additional XMP data to be added on the default XMP data just before the end of "rdf:RDF" tag. * IMPORTANT: This data is added as-is without controls, so you have to validate your data before using this method! - * @param $xmp (string) Custom XMP RDF data. + * @param string $xmp Custom XMP RDF data. * @since 6.3.0 (2019-09-19) * @public */ @@ -9551,7 +9605,7 @@ class TCPDF { /** * Put XMP data object and return ID. - * @return (int) The object ID. + * @return int The object ID. * @since 5.9.121 (2011-09-28) * @protected */ @@ -10058,8 +10112,8 @@ class TCPDF { /** * Initialize a new page. - * @param $orientation (string) page orientation. Possible values are (case insensitive):
              • P or PORTRAIT (default)
              • L or LANDSCAPE
              - * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). + * @param string $orientation page orientation. Possible values are (case insensitive):
              • P or PORTRAIT (default)
              • L or LANDSCAPE
              + * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). * @protected * @see getPageSizeFromFormat(), setPageFormat() */ @@ -10123,13 +10177,13 @@ class TCPDF { /** * Return the starting object string for the selected object ID. - * @param $objid (int) Object ID (leave empty to get a new ID). + * @param int|null $objid Object ID (leave empty to get a new ID). * @return string the starting object string * @protected * @since 5.8.009 (2010-08-20) */ - protected function _getobj($objid='') { - if ($objid === '') { + protected function _getobj($objid=null) { + if (TCPDF_STATIC::empty_string($objid)) { ++$this->n; $objid = $this->n; } @@ -10140,9 +10194,9 @@ class TCPDF { /** * Underline text. - * @param $x (int) X coordinate - * @param $y (int) Y coordinate - * @param $txt (string) text to underline + * @param int $x X coordinate + * @param int $y Y coordinate + * @param string $txt text to underline * @protected */ protected function _dounderline($x, $y, $txt) { @@ -10152,9 +10206,9 @@ class TCPDF { /** * Underline for rectangular text area. - * @param $x (int) X coordinate - * @param $y (int) Y coordinate - * @param $w (int) width to underline + * @param int $x X coordinate + * @param int $y Y coordinate + * @param int $w width to underline * @protected * @since 4.8.008 (2009-09-29) */ @@ -10165,9 +10219,9 @@ class TCPDF { /** * Line through text. - * @param $x (int) X coordinate - * @param $y (int) Y coordinate - * @param $txt (string) text to linethrough + * @param int $x X coordinate + * @param int $y Y coordinate + * @param string $txt text to linethrough * @protected */ protected function _dolinethrough($x, $y, $txt) { @@ -10177,9 +10231,9 @@ class TCPDF { /** * Line through for rectangular text area. - * @param $x (int) X coordinate - * @param $y (int) Y coordinate - * @param $w (int) line length (width) + * @param int $x X coordinate + * @param int $y Y coordinate + * @param int $w line length (width) * @protected * @since 4.9.008 (2009-09-29) */ @@ -10190,9 +10244,9 @@ class TCPDF { /** * Overline text. - * @param $x (int) X coordinate - * @param $y (int) Y coordinate - * @param $txt (string) text to overline + * @param int $x X coordinate + * @param int $y Y coordinate + * @param string $txt text to overline * @protected * @since 4.9.015 (2010-04-19) */ @@ -10203,9 +10257,9 @@ class TCPDF { /** * Overline for rectangular text area. - * @param $x (int) X coordinate - * @param $y (int) Y coordinate - * @param $w (int) width to overline + * @param int $x X coordinate + * @param int $y Y coordinate + * @param int $w width to overline * @protected * @since 4.9.015 (2010-04-19) */ @@ -10217,8 +10271,8 @@ class TCPDF { /** * Format a data string for meta information - * @param $s (string) data string to escape. - * @param $n (int) object ID + * @param string $s data string to escape. + * @param int $n object ID * @return string escaped string. * @protected */ @@ -10232,7 +10286,7 @@ class TCPDF { /** * Set the document creation timestamp - * @param $time (mixed) Document creation timestamp in seconds or date-time string. + * @param mixed $time Document creation timestamp in seconds or date-time string. * @public * @since 5.9.152 (2012-03-23) */ @@ -10245,7 +10299,7 @@ class TCPDF { /** * Set the document modification timestamp - * @param $time (mixed) Document modification timestamp in seconds or date-time string. + * @param mixed $time Document modification timestamp in seconds or date-time string. * @public * @since 5.9.152 (2012-03-23) */ @@ -10258,7 +10312,7 @@ class TCPDF { /** * Returns document creation timestamp in seconds. - * @return (int) Creation timestamp in seconds. + * @return int Creation timestamp in seconds. * @public * @since 5.9.152 (2012-03-23) */ @@ -10268,7 +10322,7 @@ class TCPDF { /** * Returns document modification timestamp in seconds. - * @return (int) Modfication timestamp in seconds. + * @return int Modfication timestamp in seconds. * @public * @since 5.9.152 (2012-03-23) */ @@ -10278,8 +10332,8 @@ class TCPDF { /** * Returns a formatted date for meta information - * @param $n (int) Object ID. - * @param $timestamp (int) Timestamp to convert. + * @param int $n Object ID. + * @param int $timestamp Timestamp to convert. * @return string escaped date string. * @protected * @since 4.6.028 (2009-08-25) @@ -10293,8 +10347,8 @@ class TCPDF { /** * Format a text string for meta information - * @param $s (string) string to escape. - * @param $n (int) object ID + * @param string $s string to escape. + * @param int $n object ID * @return string escaped string. * @protected */ @@ -10308,8 +10362,8 @@ class TCPDF { /** * get raw output stream. - * @param $s (string) string to output. - * @param $n (int) object reference for encryption mode + * @param string $s string to output. + * @param int $n object reference for encryption mode * @protected * @author Nicola Asuni * @since 5.5.000 (2010-06-22) @@ -10324,7 +10378,7 @@ class TCPDF { /** * Output a string to the document. - * @param $s (string) string to output. + * @param string $s string to output. * @protected */ protected function _out($s) { @@ -10352,7 +10406,8 @@ class TCPDF { /** * Set header font. - * @param $font (array) Array describing the basic font parameters: (family, style, size). + * @param array $font Array describing the basic font parameters: (family, style, size). + * @phpstan-param array{0: string, 1: string, 2: float|null} $font * @public * @since 1.1 */ @@ -10362,7 +10417,8 @@ class TCPDF { /** * Get header font. - * @return array() Array describing the basic font parameters: (family, style, size). + * @return array Array describing the basic font parameters: (family, style, size). + * @phpstan-return array{0: string, 1: string, 2: float|null} * @public * @since 4.0.012 (2008-07-24) */ @@ -10372,7 +10428,8 @@ class TCPDF { /** * Set footer font. - * @param $font (array) Array describing the basic font parameters: (family, style, size). + * @param array $font Array describing the basic font parameters: (family, style, size). + * @phpstan-param array{0: string, 1: string, 2: float|null} $font * @public * @since 1.1 */ @@ -10382,7 +10439,8 @@ class TCPDF { /** * Get Footer font. - * @return array() Array describing the basic font parameters: (family, style, size). + * @return array Array describing the basic font parameters: (family, style, size). + * @phpstan-return array{0: string, 1: string, 2: float|null} $font * @public * @since 4.0.012 (2008-07-24) */ @@ -10392,7 +10450,7 @@ class TCPDF { /** * Set language array. - * @param $language (array) + * @param array $language * @public * @since 1.1 */ @@ -10418,17 +10476,17 @@ class TCPDF { /** * Output anchor link. - * @param $url (string) link URL or internal link (i.e.: <a href="#23,4.5">link to page 23 at 4.5 Y position</a>) - * @param $name (string) link name - * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). - * @param $firstline (boolean) if true prints only the first line and return the remaining string. - * @param $color (array) array of RGB text color - * @param $style (string) font style (U, D, B, I) - * @param $firstblock (boolean) if true the string is the starting of a line. - * @return the number of cells used or the remaining text if $firstline = true; + * @param string $url link URL or internal link (i.e.: <a href="#23,4.5">link to page 23 at 4.5 Y position</a>) + * @param string $name link name + * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). + * @param boolean $firstline if true prints only the first line and return the remaining string. + * @param array|null $color array of RGB text color + * @param string $style font style (U, D, B, I) + * @param boolean $firstblock if true the string is the starting of a line. + * @return int the number of cells used or the remaining text if $firstline = true; * @public */ - public function addHtmlLink($url, $name, $fill=false, $firstline=false, $color='', $style=-1, $firstblock=false) { + public function addHtmlLink($url, $name, $fill=false, $firstline=false, $color=null, $style=-1, $firstblock=false) { if (isset($url[1]) AND ($url[0] == '#') AND is_numeric($url[1])) { // convert url to internal link $lnkdata = explode(',', $url); @@ -10440,32 +10498,32 @@ class TCPDF { $lnky = 0; } $url = $this->AddLink(); - $this->SetLink($url, $lnky, $page); + $this->setLink($url, $lnky, $page); } } // store current settings $prevcolor = $this->fgcolor; $prevstyle = $this->FontStyle; if (empty($color)) { - $this->SetTextColorArray($this->htmlLinkColorArray); + $this->setTextColorArray($this->htmlLinkColorArray); } else { - $this->SetTextColorArray($color); + $this->setTextColorArray($color); } if ($style == -1) { - $this->SetFont('', $this->FontStyle.$this->htmlLinkFontStyle); + $this->setFont('', $this->FontStyle.$this->htmlLinkFontStyle); } else { - $this->SetFont('', $this->FontStyle.$style); + $this->setFont('', $this->FontStyle.$style); } $ret = $this->Write($this->lasth, $name, $url, $fill, '', false, 0, $firstline, $firstblock, 0); // restore settings - $this->SetFont('', $prevstyle); - $this->SetTextColorArray($prevcolor); + $this->setFont('', $prevstyle); + $this->setTextColorArray($prevcolor); return $ret; } /** * Converts pixels to User's Units. - * @param $px (int) pixels + * @param int $px pixels * @return float value in user's unit * @public * @see setImageScale(), getImageScale() @@ -10477,7 +10535,7 @@ class TCPDF { /** * Reverse function for htmlentities. * Convert entities in UTF-8. - * @param $text_to_convert (string) Text to convert. + * @param string $text_to_convert Text to convert. * @return string converted text string * @public */ @@ -10490,7 +10548,7 @@ class TCPDF { /** * Compute encryption key depending on object number where the encrypted data is stored. * This is used for all strings and streams without crypt filter specifier. - * @param $n (int) object number + * @param int $n object number * @return int object key * @protected * @author Nicola Asuni @@ -10509,9 +10567,9 @@ class TCPDF { /** * Encrypt the input string. - * @param $n (int) object number - * @param $s (string) data string to encrypt - * @return encrypted string + * @param int $n object number + * @param string $s data string to encrypt + * @return string encrypted string * @protected * @author Nicola Asuni * @since 5.0.005 (2010-05-11) @@ -10754,7 +10812,7 @@ class TCPDF { /** * Convert password for AES-256 encryption mode - * @param $password (string) password + * @param string $password password * @return string password * @protected * @since 5.9.006 (2010-10-19) @@ -10884,16 +10942,16 @@ class TCPDF { * Remark: the protection against modification is for people who have the full Acrobat product. * If you don't set any password, the document will open as usual. If you set a user password, the PDF viewer will ask for it before displaying the document. The master password, if different from the user one, can be used to get full access. * Note: protecting a document requires to encrypt it, which increases the processing time a lot. This can cause a PHP time-out in some cases, especially if the document contains images or fonts. - * @param $permissions (Array) the set of permissions (specify the ones you want to block):
              • print : Print the document;
              • modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
              • copy : Copy or otherwise extract text and graphics from the document;
              • annot-forms : Add or modify text annotations, fill in interactive form fields, and, if 'modify' is also set, create or modify interactive form fields (including signature fields);
              • fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
              • extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
              • assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
              • print-high : Print the document to a representation from which a faithful digital copy of the PDF content could be generated. When this is not set, printing is limited to a low-level representation of the appearance, possibly of degraded quality.
              • owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
              - * @param $user_pass (String) user password. Empty by default. - * @param $owner_pass (String) owner password. If not specified, a random value is used. - * @param $mode (int) encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit. - * @param $pubkeys (String) array of recipients containing public-key certificates ('c') and permissions ('p'). For example: array(array('c' => 'file://../examples/data/cert/tcpdf.crt', 'p' => array('print'))) + * @param array $permissions the set of permissions (specify the ones you want to block):
              • print : Print the document;
              • modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
              • copy : Copy or otherwise extract text and graphics from the document;
              • annot-forms : Add or modify text annotations, fill in interactive form fields, and, if 'modify' is also set, create or modify interactive form fields (including signature fields);
              • fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
              • extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
              • assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
              • print-high : Print the document to a representation from which a faithful digital copy of the PDF content could be generated. When this is not set, printing is limited to a low-level representation of the appearance, possibly of degraded quality.
              • owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
              + * @param string $user_pass user password. Empty by default. + * @param string|null $owner_pass owner password. If not specified, a random value is used. + * @param int $mode encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit. + * @param array|null $pubkeys array of recipients containing public-key certificates ('c') and permissions ('p'). For example: array(array('c' => 'file://../examples/data/cert/tcpdf.crt', 'p' => array('print'))) * @public * @since 2.0.000 (2008-01-02) * @author Nicola Asuni */ - public function SetProtection($permissions=array('print', 'modify', 'copy', 'annot-forms', 'fill-forms', 'extract', 'assemble', 'print-high'), $user_pass='', $owner_pass=null, $mode=0, $pubkeys=null) { + public function setProtection($permissions=array('print', 'modify', 'copy', 'annot-forms', 'fill-forms', 'extract', 'assemble', 'print-high'), $user_pass='', $owner_pass=null, $mode=0, $pubkeys=null) { if ($this->pdfa_mode) { // encryption is not allowed in PDF/A mode return; @@ -11040,9 +11098,9 @@ class TCPDF { } /** * Horizontal Scaling. - * @param $s_x (float) scaling factor for width as percent. 0 is not allowed. - * @param $x (int) abscissa of the scaling center. Default is current x position - * @param $y (int) ordinate of the scaling center. Default is current y position + * @param float $s_x scaling factor for width as percent. 0 is not allowed. + * @param int $x abscissa of the scaling center. Default is current x position + * @param int $y ordinate of the scaling center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() @@ -11053,9 +11111,9 @@ class TCPDF { /** * Vertical Scaling. - * @param $s_y (float) scaling factor for height as percent. 0 is not allowed. - * @param $x (int) abscissa of the scaling center. Default is current x position - * @param $y (int) ordinate of the scaling center. Default is current y position + * @param float $s_y scaling factor for height as percent. 0 is not allowed. + * @param int $x abscissa of the scaling center. Default is current x position + * @param int $y ordinate of the scaling center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() @@ -11066,9 +11124,9 @@ class TCPDF { /** * Vertical and horizontal proportional Scaling. - * @param $s (float) scaling factor for width and height as percent. 0 is not allowed. - * @param $x (int) abscissa of the scaling center. Default is current x position - * @param $y (int) ordinate of the scaling center. Default is current y position + * @param float $s scaling factor for width and height as percent. 0 is not allowed. + * @param int $x abscissa of the scaling center. Default is current x position + * @param int $y ordinate of the scaling center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() @@ -11079,19 +11137,19 @@ class TCPDF { /** * Vertical and horizontal non-proportional Scaling. - * @param $s_x (float) scaling factor for width as percent. 0 is not allowed. - * @param $s_y (float) scaling factor for height as percent. 0 is not allowed. - * @param $x (int) abscissa of the scaling center. Default is current x position - * @param $y (int) ordinate of the scaling center. Default is current y position + * @param float $s_x scaling factor for width as percent. 0 is not allowed. + * @param float $s_y scaling factor for height as percent. 0 is not allowed. + * @param float|null $x abscissa of the scaling center. Default is current x position + * @param float|null $y ordinate of the scaling center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ - public function Scale($s_x, $s_y, $x='', $y='') { - if ($x === '') { + public function Scale($s_x, $s_y, $x=null, $y=null) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } if (($s_x == 0) OR ($s_y == 0)) { @@ -11115,55 +11173,55 @@ class TCPDF { /** * Horizontal Mirroring. - * @param $x (int) abscissa of the point. Default is current x position + * @param float|null $x abscissa of the point. Default is current x position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ - public function MirrorH($x='') { + public function MirrorH($x=null) { $this->Scale(-100, 100, $x); } /** * Verical Mirroring. - * @param $y (int) ordinate of the point. Default is current y position + * @param float|null $y ordinate of the point. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ - public function MirrorV($y='') { - $this->Scale(100, -100, '', $y); + public function MirrorV($y=null) { + $this->Scale(100, -100, null, $y); } /** * Point reflection mirroring. - * @param $x (int) abscissa of the point. Default is current x position - * @param $y (int) ordinate of the point. Default is current y position + * @param float|null $x abscissa of the point. Default is current x position + * @param float|null $y ordinate of the point. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ - public function MirrorP($x='',$y='') { + public function MirrorP($x=null,$y=null) { $this->Scale(-100, -100, $x, $y); } /** * Reflection against a straight line through point (x, y) with the gradient angle (angle). - * @param $angle (float) gradient angle of the straight line. Default is 0 (horizontal line). - * @param $x (int) abscissa of the point. Default is current x position - * @param $y (int) ordinate of the point. Default is current y position + * @param float $angle gradient angle of the straight line. Default is 0 (horizontal line). + * @param float|null $x abscissa of the point. Default is current x position + * @param float|null $y ordinate of the point. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ - public function MirrorL($angle=0, $x='',$y='') { + public function MirrorL($angle=0, $x=null,$y=null) { $this->Scale(-100, 100, $x, $y); $this->Rotate(-2*($angle-90), $x, $y); } /** * Translate graphic object horizontally. - * @param $t_x (int) movement to the right (or left for RTL) + * @param int $t_x movement to the right (or left for RTL) * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() @@ -11174,7 +11232,7 @@ class TCPDF { /** * Translate graphic object vertically. - * @param $t_y (int) movement to the bottom + * @param int $t_y movement to the bottom * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() @@ -11185,8 +11243,8 @@ class TCPDF { /** * Translate graphic object horizontally and vertically. - * @param $t_x (int) movement to the right - * @param $t_y (int) movement to the bottom + * @param int $t_x movement to the right + * @param int $t_y movement to the bottom * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() @@ -11206,18 +11264,18 @@ class TCPDF { /** * Rotate object. - * @param $angle (float) angle in degrees for counter-clockwise rotation - * @param $x (int) abscissa of the rotation center. Default is current x position - * @param $y (int) ordinate of the rotation center. Default is current y position + * @param float $angle angle in degrees for counter-clockwise rotation + * @param float|null $x abscissa of the rotation center. Default is current x position + * @param float|null $y ordinate of the rotation center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ - public function Rotate($angle, $x='', $y='') { - if ($x === '') { + public function Rotate($angle, $x=null, $y=null) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } $y = ($this->h - $y) * $this->k; @@ -11236,45 +11294,45 @@ class TCPDF { /** * Skew horizontally. - * @param $angle_x (float) angle in degrees between -90 (skew to the left) and 90 (skew to the right) - * @param $x (int) abscissa of the skewing center. default is current x position - * @param $y (int) ordinate of the skewing center. default is current y position + * @param float $angle_x angle in degrees between -90 (skew to the left) and 90 (skew to the right) + * @param float|null $x abscissa of the skewing center. default is current x position + * @param float|null $y ordinate of the skewing center. default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ - public function SkewX($angle_x, $x='', $y='') { + public function SkewX($angle_x, $x=null, $y=null) { $this->Skew($angle_x, 0, $x, $y); } /** * Skew vertically. - * @param $angle_y (float) angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) - * @param $x (int) abscissa of the skewing center. default is current x position - * @param $y (int) ordinate of the skewing center. default is current y position + * @param float $angle_y angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) + * @param float|null $x abscissa of the skewing center. default is current x position + * @param float|null $y ordinate of the skewing center. default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ - public function SkewY($angle_y, $x='', $y='') { + public function SkewY($angle_y, $x=null, $y=null) { $this->Skew(0, $angle_y, $x, $y); } /** * Skew. - * @param $angle_x (float) angle in degrees between -90 (skew to the left) and 90 (skew to the right) - * @param $angle_y (float) angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) - * @param $x (int) abscissa of the skewing center. default is current x position - * @param $y (int) ordinate of the skewing center. default is current y position + * @param float $angle_x angle in degrees between -90 (skew to the left) and 90 (skew to the right) + * @param float $angle_y angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) + * @param float|null $x abscissa of the skewing center. default is current x position + * @param float|null $y ordinate of the skewing center. default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ - public function Skew($angle_x, $angle_y, $x='', $y='') { - if ($x === '') { + public function Skew($angle_x, $angle_y, $x=null, $y=null) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } if (($angle_x <= -90) OR ($angle_x >= 90) OR ($angle_y <= -90) OR ($angle_y >= 90)) { @@ -11296,7 +11354,7 @@ class TCPDF { /** * Apply graphic transformations. - * @param $tm (array) transformation matrix + * @param array $tm transformation matrix * @protected * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() @@ -11328,12 +11386,12 @@ class TCPDF { /** * Defines the line width. By default, the value equals 0.2 mm. The method can be called before the first page is created and the value is retained from page to page. - * @param $width (float) The width. + * @param float $width The width. * @public * @since 1.0 * @see Line(), Rect(), Cell(), MultiCell() */ - public function SetLineWidth($width) { + public function setLineWidth($width) { //Set line width $this->LineWidth = $width; $this->linestyleWidth = sprintf('%F w', ($width * $this->k)); @@ -11355,7 +11413,7 @@ class TCPDF { /** * Set line style. - * @param $style (array) Line style. Array with keys among the following: + * @param array $style Line style. Array with keys among the following: *
                *
              • width (float): Width of the line in user units.
              • *
              • cap (string): Type of cap to put on the line. Possible values are: @@ -11371,15 +11429,15 @@ class TCPDF { * the point at which the pattern starts.
              • *
              • color (array): Draw color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName).
              • *
              - * @param $ret (boolean) if true do not send the command. + * @param boolean $ret if true do not send the command. * @return string the PDF command * @public * @since 2.1.000 (2008-01-08) */ - public function SetLineStyle($style, $ret=false) { + public function setLineStyle($style, $ret=false) { $s = ''; // string to be returned if (!is_array($style)) { - return; + return $s; } if (isset($style['width'])) { $this->LineWidth = $style['width']; @@ -11423,7 +11481,7 @@ class TCPDF { $s .= $this->linestyleDash.' '; } if (isset($style['color'])) { - $s .= $this->SetDrawColorArray($style['color'], true).' '; + $s .= $this->setDrawColorArray($style['color'], true).' '; } if (!$ret AND ($this->state == 2)) { $this->_out($s); @@ -11433,8 +11491,8 @@ class TCPDF { /** * Begin a new subpath by moving the current point to coordinates (x, y), omitting any connecting line segment. - * @param $x (float) Abscissa of point. - * @param $y (float) Ordinate of point. + * @param float $x Abscissa of point. + * @param float $y Ordinate of point. * @protected * @since 2.1.000 (2008-01-08) */ @@ -11447,8 +11505,8 @@ class TCPDF { /** * Append a straight line segment from the current point to the point (x, y). * The new current point shall be (x, y). - * @param $x (float) Abscissa of end point. - * @param $y (float) Ordinate of end point. + * @param float $x Abscissa of end point. + * @param float $y Ordinate of end point. * @protected * @since 2.1.000 (2008-01-08) */ @@ -11460,11 +11518,11 @@ class TCPDF { /** * Append a rectangle to the current path as a complete subpath, with lower-left corner (x, y) and dimensions widthand height in user space. - * @param $x (float) Abscissa of upper-left corner. - * @param $y (float) Ordinate of upper-left corner. - * @param $w (float) Width. - * @param $h (float) Height. - * @param $op (string) options + * @param float $x Abscissa of upper-left corner. + * @param float $y Ordinate of upper-left corner. + * @param float $w Width. + * @param float $h Height. + * @param string $op options * @protected * @since 2.1.000 (2008-01-08) */ @@ -11477,12 +11535,12 @@ class TCPDF { /** * Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using (x1, y1) and (x2, y2) as the Bezier control points. * The new current point shall be (x3, y3). - * @param $x1 (float) Abscissa of control point 1. - * @param $y1 (float) Ordinate of control point 1. - * @param $x2 (float) Abscissa of control point 2. - * @param $y2 (float) Ordinate of control point 2. - * @param $x3 (float) Abscissa of end point. - * @param $y3 (float) Ordinate of end point. + * @param float $x1 Abscissa of control point 1. + * @param float $y1 Ordinate of control point 1. + * @param float $x2 Abscissa of control point 2. + * @param float $y2 Ordinate of control point 2. + * @param float $x3 Abscissa of end point. + * @param float $y3 Ordinate of end point. * @protected * @since 2.1.000 (2008-01-08) */ @@ -11495,10 +11553,10 @@ class TCPDF { /** * Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using the current point and (x2, y2) as the Bezier control points. * The new current point shall be (x3, y3). - * @param $x2 (float) Abscissa of control point 2. - * @param $y2 (float) Ordinate of control point 2. - * @param $x3 (float) Abscissa of end point. - * @param $y3 (float) Ordinate of end point. + * @param float $x2 Abscissa of control point 2. + * @param float $y2 Ordinate of control point 2. + * @param float $x3 Abscissa of end point. + * @param float $y3 Ordinate of end point. * @protected * @since 4.9.019 (2010-04-26) */ @@ -11511,10 +11569,10 @@ class TCPDF { /** * Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using (x1, y1) and (x3, y3) as the Bezier control points. * The new current point shall be (x3, y3). - * @param $x1 (float) Abscissa of control point 1. - * @param $y1 (float) Ordinate of control point 1. - * @param $x3 (float) Abscissa of end point. - * @param $y3 (float) Ordinate of end point. + * @param float $x1 Abscissa of control point 1. + * @param float $y1 Ordinate of control point 1. + * @param float $x3 Abscissa of end point. + * @param float $y3 Ordinate of end point. * @protected * @since 2.1.000 (2008-01-08) */ @@ -11526,11 +11584,11 @@ class TCPDF { /** * Draws a line between two points. - * @param $x1 (float) Abscissa of first point. - * @param $y1 (float) Ordinate of first point. - * @param $x2 (float) Abscissa of second point. - * @param $y2 (float) Ordinate of second point. - * @param $style (array) Line style. Array like for SetLineStyle(). Default value: default line style (empty array). + * @param float $x1 Abscissa of first point. + * @param float $y1 Ordinate of first point. + * @param float $x2 Abscissa of second point. + * @param float $y2 Ordinate of second point. + * @param array $style Line style. Array like for SetLineStyle(). Default value: default line style (empty array). * @public * @since 1.0 * @see SetLineWidth(), SetDrawColor(), SetLineStyle() @@ -11540,7 +11598,7 @@ class TCPDF { return; } if (is_array($style)) { - $this->SetLineStyle($style); + $this->setLineStyle($style); } $this->_outPoint($x1, $y1); $this->_outLine($x2, $y2); @@ -11549,18 +11607,18 @@ class TCPDF { /** * Draws a rectangle. - * @param $x (float) Abscissa of upper-left corner. - * @param $y (float) Ordinate of upper-left corner. - * @param $w (float) Width. - * @param $h (float) Height. - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $border_style (array) Border style of rectangle. Array with keys among the following: + * @param float $x Abscissa of upper-left corner. + * @param float $y Ordinate of upper-left corner. + * @param float $w Width. + * @param float $h Height. + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $border_style Border style of rectangle. Array with keys among the following: *
                *
              • all: Line style of all borders. Array like for SetLineStyle().
              • *
              • L, T, R, B or combinations: Line style of left, top, right or bottom border. Array like for SetLineStyle().
              • *
              * If a key is not present or is null, the correspondent border is not drawn. Default value: default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). + * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). * @public * @since 1.0 * @see SetLineStyle() @@ -11574,12 +11632,12 @@ class TCPDF { } if (!(strpos($style, 'F') === false) AND !empty($fill_color)) { // set background color - $this->SetFillColorArray($fill_color); + $this->setFillColorArray($fill_color); } if (!empty($border_style)) { if (isset($border_style['all']) AND !empty($border_style['all'])) { //set global style for border - $this->SetLineStyle($border_style['all']); + $this->setLineStyle($border_style['all']); $border_style = array(); } else { // remove stroke operator from style @@ -11621,17 +11679,17 @@ class TCPDF { * Draws a Bezier curve. * The Bezier curve is a tangent to the line between the control points at * either end of the curve. - * @param $x0 (float) Abscissa of start point. - * @param $y0 (float) Ordinate of start point. - * @param $x1 (float) Abscissa of control point 1. - * @param $y1 (float) Ordinate of control point 1. - * @param $x2 (float) Abscissa of control point 2. - * @param $y2 (float) Ordinate of control point 2. - * @param $x3 (float) Abscissa of end point. - * @param $y3 (float) Ordinate of end point. - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $line_style (array) Line style of curve. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). + * @param float $x0 Abscissa of start point. + * @param float $y0 Ordinate of start point. + * @param float $x1 Abscissa of control point 1. + * @param float $y1 Ordinate of control point 1. + * @param float $x2 Abscissa of control point 2. + * @param float $y2 Ordinate of control point 2. + * @param float $x3 Abscissa of end point. + * @param float $y3 Ordinate of end point. + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $line_style Line style of curve. Array like for SetLineStyle(). Default value: default line style (empty array). + * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). * @public * @see SetLineStyle() * @since 2.1.000 (2008-01-08) @@ -11641,11 +11699,11 @@ class TCPDF { return; } if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->SetFillColorArray($fill_color); + $this->setFillColorArray($fill_color); } $op = TCPDF_STATIC::getPathPaintOperator($style); if ($line_style) { - $this->SetLineStyle($line_style); + $this->setLineStyle($line_style); } $this->_outPoint($x0, $y0); $this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3); @@ -11656,12 +11714,12 @@ class TCPDF { * Draws a poly-Bezier curve. * Each Bezier curve segment is a tangent to the line between the control points at * either end of the curve. - * @param $x0 (float) Abscissa of start point. - * @param $y0 (float) Ordinate of start point. - * @param $segments (float) An array of bezier descriptions. Format: array(x1, y1, x2, y2, x3, y3). - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $line_style (array) Line style of curve. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). + * @param float $x0 Abscissa of start point. + * @param float $y0 Ordinate of start point. + * @param float[] $segments An array of bezier descriptions. Format: array(x1, y1, x2, y2, x3, y3). + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $line_style Line style of curve. Array like for SetLineStyle(). Default value: default line style (empty array). + * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). * @public * @see SetLineStyle() * @since 3.0008 (2008-05-12) @@ -11671,14 +11729,14 @@ class TCPDF { return; } if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->SetFillColorArray($fill_color); + $this->setFillColorArray($fill_color); } $op = TCPDF_STATIC::getPathPaintOperator($style); if ($op == 'f') { $line_style = array(); } if ($line_style) { - $this->SetLineStyle($line_style); + $this->setLineStyle($line_style); } $this->_outPoint($x0, $y0); foreach ($segments as $segment) { @@ -11691,22 +11749,22 @@ class TCPDF { /** * Draws an ellipse. * An ellipse is formed from n Bezier curves. - * @param $x0 (float) Abscissa of center point. - * @param $y0 (float) Ordinate of center point. - * @param $rx (float) Horizontal radius. - * @param $ry (float) Vertical radius (if ry = 0 then is a circle, see Circle()). Default value: 0. - * @param $angle: (float) Angle oriented (anti-clockwise). Default value: 0. - * @param $astart: (float) Angle start of draw line. Default value: 0. - * @param $afinish: (float) Angle finish of draw line. Default value: 360. - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $line_style (array) Line style of ellipse. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @param $nc (integer) Number of curves used to draw a 90 degrees portion of ellipse. + * @param float $x0 Abscissa of center point. + * @param float $y0 Ordinate of center point. + * @param float $rx Horizontal radius. + * @param float $ry Vertical radius (if ry = 0 then is a circle, see Circle()). Default value: 0. + * @param float $angle Angle oriented (anti-clockwise). Default value: 0. + * @param float $astart Angle start of draw line. Default value: 0. + * @param float $afinish Angle finish of draw line. Default value: 360. + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $line_style Line style of ellipse. Array like for SetLineStyle(). Default value: default line style (empty array). + * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). + * @param integer $nc Number of curves used to draw a 90 degrees portion of ellipse. * @author Nicola Asuni * @public * @since 2.1.000 (2008-01-08) */ - public function Ellipse($x0, $y0, $rx, $ry='', $angle=0, $astart=0, $afinish=360, $style='', $line_style=array(), $fill_color=array(), $nc=2) { + public function Ellipse($x0, $y0, $rx, $ry=0, $angle=0, $astart=0, $afinish=360, $style='', $line_style=array(), $fill_color=array(), $nc=2) { if ($this->state != 2) { return; } @@ -11714,14 +11772,14 @@ class TCPDF { $ry = $rx; } if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->SetFillColorArray($fill_color); + $this->setFillColorArray($fill_color); } $op = TCPDF_STATIC::getPathPaintOperator($style); if ($op == 'f') { $line_style = array(); } if ($line_style) { - $this->SetLineStyle($line_style); + $this->setLineStyle($line_style); } $this->_outellipticalarc($x0, $y0, $rx, $ry, $angle, $astart, $afinish, false, $nc, true, true, false); $this->_out($op); @@ -11730,18 +11788,18 @@ class TCPDF { /** * Append an elliptical arc to the current path. * An ellipse is formed from n Bezier curves. - * @param $xc (float) Abscissa of center point. - * @param $yc (float) Ordinate of center point. - * @param $rx (float) Horizontal radius. - * @param $ry (float) Vertical radius (if ry = 0 then is a circle, see Circle()). Default value: 0. - * @param $xang: (float) Angle between the X-axis and the major axis of the ellipse. Default value: 0. - * @param $angs: (float) Angle start of draw line. Default value: 0. - * @param $angf: (float) Angle finish of draw line. Default value: 360. - * @param $pie (boolean) if true do not mark the border point (used to draw pie sectors). - * @param $nc (integer) Number of curves used to draw a 90 degrees portion of ellipse. - * @param $startpoint (boolean) if true output a starting point. - * @param $ccw (boolean) if true draws in counter-clockwise. - * @param $svg (boolean) if true the angles are in svg mode (already calculated). + * @param float $xc Abscissa of center point. + * @param float $yc Ordinate of center point. + * @param float $rx Horizontal radius. + * @param float $ry Vertical radius (if ry = 0 then is a circle, see Circle()). Default value: 0. + * @param float $xang Angle between the X-axis and the major axis of the ellipse. Default value: 0. + * @param float $angs Angle start of draw line. Default value: 0. + * @param float $angf Angle finish of draw line. Default value: 360. + * @param boolean $pie if true do not mark the border point (used to draw pie sectors). + * @param integer $nc Number of curves used to draw a 90 degrees portion of ellipse. + * @param boolean $startpoint if true output a starting point. + * @param boolean $ccw if true draws in counter-clockwise. + * @param boolean $svg if true the angles are in svg mode (already calculated). * @return array bounding box coordinates (x min, y min, x max, y max) * @author Nicola Asuni * @protected @@ -11866,15 +11924,15 @@ class TCPDF { /** * Draws a circle. * A circle is formed from n Bezier curves. - * @param $x0 (float) Abscissa of center point. - * @param $y0 (float) Ordinate of center point. - * @param $r (float) Radius. - * @param $angstr: (float) Angle start of draw line. Default value: 0. - * @param $angend: (float) Angle finish of draw line. Default value: 360. - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $line_style (array) Line style of circle. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(red, green, blue). Default value: default color (empty array). - * @param $nc (integer) Number of curves used to draw a 90 degrees portion of circle. + * @param float $x0 Abscissa of center point. + * @param float $y0 Ordinate of center point. + * @param float $r Radius. + * @param float $angstr Angle start of draw line. Default value: 0. + * @param float $angend Angle finish of draw line. Default value: 360. + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $line_style Line style of circle. Array like for SetLineStyle(). Default value: default line style (empty array). + * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). + * @param integer $nc Number of curves used to draw a 90 degrees portion of circle. * @public * @since 2.1.000 (2008-01-08) */ @@ -11884,15 +11942,15 @@ class TCPDF { /** * Draws a polygonal line - * @param $p (array) Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1)) - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $line_style (array) Line style of polygon. Array with keys among the following: + * @param array $p Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1)) + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $line_style Line style of polygon. Array with keys among the following: *
                *
              • all: Line style of all lines. Array like for SetLineStyle().
              • *
              • 0 to ($np - 1): Line style of each line. Array like for SetLineStyle().
              • *
              * If a key is not present or is null, not draws the line. Default value is default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). + * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). * @since 4.8.003 (2009-09-15) * @public */ @@ -11902,16 +11960,16 @@ class TCPDF { /** * Draws a polygon. - * @param $p (array) Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1)) - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $line_style (array) Line style of polygon. Array with keys among the following: + * @param array $p Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1)) + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $line_style Line style of polygon. Array with keys among the following: *
                *
              • all: Line style of all lines. Array like for SetLineStyle().
              • *
              • 0 to ($np - 1): Line style of each line. Array like for SetLineStyle().
              • *
              * If a key is not present or is null, not draws the line. Default value is default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @param $closed (boolean) if true the polygon is closes, otherwise will remain open + * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). + * @param boolean $closed if true the polygon is closes, otherwise will remain open * @public * @since 2.1.000 (2008-01-08) */ @@ -11933,7 +11991,7 @@ class TCPDF { $nc += 4; } if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->SetFillColorArray($fill_color); + $this->setFillColorArray($fill_color); } $op = TCPDF_STATIC::getPathPaintOperator($style); if ($op == 'f') { @@ -11942,7 +12000,7 @@ class TCPDF { $draw = true; if ($line_style) { if (isset($line_style['all'])) { - $this->SetLineStyle($line_style['all']); + $this->setLineStyle($line_style['all']); } else { $draw = false; if ($op == 'B') { @@ -11962,7 +12020,7 @@ class TCPDF { if ($line_style[$line_num] != 0) { if (is_array($line_style[$line_num])) { $this->_out('S'); - $this->SetLineStyle($line_style[$line_num]); + $this->setLineStyle($line_style[$line_num]); $this->_outPoint($p[$i - 2], $p[$i - 1]); $this->_outLine($p[$i], $p[$i + 1]); $this->_out('S'); @@ -11989,21 +12047,21 @@ class TCPDF { /** * Draws a regular polygon. - * @param $x0 (float) Abscissa of center point. - * @param $y0 (float) Ordinate of center point. - * @param $r: (float) Radius of inscribed circle. - * @param $ns (integer) Number of sides. - * @param $angle (float) Angle oriented (anti-clockwise). Default value: 0. - * @param $draw_circle (boolean) Draw inscribed circle or not. Default value: false. - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $line_style (array) Line style of polygon sides. Array with keys among the following: + * @param float $x0 Abscissa of center point. + * @param float $y0 Ordinate of center point. + * @param float $r Radius of inscribed circle. + * @param integer $ns Number of sides. + * @param float $angle Angle oriented (anti-clockwise). Default value: 0. + * @param boolean $draw_circle Draw inscribed circle or not. Default value: false. + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $line_style Line style of polygon sides. Array with keys among the following: *
                *
              • all: Line style of all sides. Array like for SetLineStyle().
              • *
              • 0 to ($ns - 1): Line style of each side. Array like for SetLineStyle().
              • *
              * If a key is not present or is null, not draws the side. Default value is default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(red, green, blue). Default value: default color (empty array). - * @param $circle_style (string) Style of rendering of inscribed circle (if draws). Possible values are: + * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). + * @param string $circle_style Style of rendering of inscribed circle (if draws). Possible values are: *
                *
              • D or empty string: Draw (default).
              • *
              • F: Fill.
              • @@ -12011,8 +12069,8 @@ class TCPDF { *
              • CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).
              • *
              • CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).
              • *
              - * @param $circle_outLine_style (array) Line style of inscribed circle (if draws). Array like for SetLineStyle(). Default value: default line style (empty array). - * @param $circle_fill_color (array) Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). + * @param array $circle_outLine_style Line style of inscribed circle (if draws). Array like for SetLineStyle(). Default value: default line style (empty array). + * @param array $circle_fill_color Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). * @public * @since 2.1.000 (2008-01-08) */ @@ -12035,23 +12093,23 @@ class TCPDF { /** * Draws a star polygon - * @param $x0 (float) Abscissa of center point. - * @param $y0 (float) Ordinate of center point. - * @param $r (float) Radius of inscribed circle. - * @param $nv (integer) Number of vertices. - * @param $ng (integer) Number of gap (if ($ng % $nv = 1) then is a regular polygon). - * @param $angle: (float) Angle oriented (anti-clockwise). Default value: 0. - * @param $draw_circle: (boolean) Draw inscribed circle or not. Default value is false. - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $line_style (array) Line style of polygon sides. Array with keys among the following: + * @param float $x0 Abscissa of center point. + * @param float $y0 Ordinate of center point. + * @param float $r Radius of inscribed circle. + * @param integer $nv Number of vertices. + * @param integer $ng Number of gap (if ($ng % $nv = 1) then is a regular polygon). + * @param float $angle Angle oriented (anti-clockwise). Default value: 0. + * @param boolean $draw_circle Draw inscribed circle or not. Default value is false. + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $line_style Line style of polygon sides. Array with keys among the following: *
                *
              • all: Line style of all sides. Array like for * SetLineStyle().
              • *
              • 0 to (n - 1): Line style of each side. Array like for SetLineStyle().
              • *
              * If a key is not present or is null, not draws the side. Default value is default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(red, green, blue). Default value: default color (empty array). - * @param $circle_style (string) Style of rendering of inscribed circle (if draws). Possible values are: + * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). + * @param string $circle_style Style of rendering of inscribed circle (if draws). Possible values are: *
                *
              • D or empty string: Draw (default).
              • *
              • F: Fill.
              • @@ -12059,8 +12117,8 @@ class TCPDF { *
              • CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).
              • *
              • CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).
              • *
              - * @param $circle_outLine_style (array) Line style of inscribed circle (if draws). Array like for SetLineStyle(). Default value: default line style (empty array). - * @param $circle_fill_color (array) Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). + * @param array $circle_outLine_style Line style of inscribed circle (if draws). Array like for SetLineStyle(). Default value: default line style (empty array). + * @param array $circle_fill_color Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). * @public * @since 2.1.000 (2008-01-08) */ @@ -12094,15 +12152,15 @@ class TCPDF { /** * Draws a rounded rectangle. - * @param $x (float) Abscissa of upper-left corner. - * @param $y (float) Ordinate of upper-left corner. - * @param $w (float) Width. - * @param $h (float) Height. - * @param $r (float) the radius of the circle used to round off the corners of the rectangle. - * @param $round_corner (string) Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top right, bottom right, bottom left and top left. Default value: all rounded corner ("1111"). - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $border_style (array) Border style of rectangle. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). + * @param float $x Abscissa of upper-left corner. + * @param float $y Ordinate of upper-left corner. + * @param float $w Width. + * @param float $h Height. + * @param float $r the radius of the circle used to round off the corners of the rectangle. + * @param string $round_corner Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top right, bottom right, bottom left and top left. Default value: all rounded corner ("1111"). + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $border_style Border style of rectangle. Array like for SetLineStyle(). Default value: default line style (empty array). + * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). * @public * @since 2.1.000 (2008-01-08) */ @@ -12112,16 +12170,16 @@ class TCPDF { /** * Draws a rounded rectangle. - * @param $x (float) Abscissa of upper-left corner. - * @param $y (float) Ordinate of upper-left corner. - * @param $w (float) Width. - * @param $h (float) Height. - * @param $rx (float) the x-axis radius of the ellipse used to round off the corners of the rectangle. - * @param $ry (float) the y-axis radius of the ellipse used to round off the corners of the rectangle. - * @param $round_corner (string) Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top right, bottom right, bottom left and top left. Default value: all rounded corner ("1111"). - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $border_style (array) Border style of rectangle. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). + * @param float $x Abscissa of upper-left corner. + * @param float $y Ordinate of upper-left corner. + * @param float $w Width. + * @param float $h Height. + * @param float $rx the x-axis radius of the ellipse used to round off the corners of the rectangle. + * @param float $ry the y-axis radius of the ellipse used to round off the corners of the rectangle. + * @param string $round_corner Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top right, bottom right, bottom left and top left. Default value: all rounded corner ("1111"). + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param array $border_style Border style of rectangle. Array like for SetLineStyle(). Default value: default line style (empty array). + * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). * @public * @since 4.9.019 (2010-04-22) */ @@ -12136,14 +12194,14 @@ class TCPDF { } // Rounded if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->SetFillColorArray($fill_color); + $this->setFillColorArray($fill_color); } $op = TCPDF_STATIC::getPathPaintOperator($style); if ($op == 'f') { $border_style = array(); } if ($border_style) { - $this->SetLineStyle($border_style); + $this->setLineStyle($border_style); } $MyArc = 4 / 3 * (sqrt(2) - 1); $this->_outPoint($x + $rx, $y); @@ -12185,13 +12243,13 @@ class TCPDF { /** * Draws a grahic arrow. - * @param $x0 (float) Abscissa of first point. - * @param $y0 (float) Ordinate of first point. - * @param $x1 (float) Abscissa of second point. - * @param $y1 (float) Ordinate of second point. - * @param $head_style (int) (0 = draw only arrowhead arms, 1 = draw closed arrowhead, but no fill, 2 = closed and filled arrowhead, 3 = filled arrowhead) - * @param $arm_size (float) length of arrowhead arms - * @param $arm_angle (int) angle between an arm and the shaft + * @param float $x0 Abscissa of first point. + * @param float $y0 Ordinate of first point. + * @param float $x1 Abscissa of second point. + * @param float $y1 Ordinate of second point. + * @param int $head_style (0 = draw only arrowhead arms, 1 = draw closed arrowhead, but no fill, 2 = closed and filled arrowhead, 3 = filled arrowhead) + * @param float $arm_size length of arrowhead arms + * @param int $arm_angle angle between an arm and the shaft * @author Piotr Galecki, Nicola Asuni, Andy Meier * @since 4.6.018 (2009-07-10) */ @@ -12251,11 +12309,11 @@ class TCPDF { /** * Add a Named Destination. * NOTE: destination names are unique, so only last entry will be saved. - * @param $name (string) Destination name. - * @param $y (float) Y position in user units of the destiantion on the selected page (default = -1 = current position; 0 = page start;). - * @param $page (int|string) Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. - * @param $x (float) X position in user units of the destiantion on the selected page (default = -1 = current position;). - * @return (string) Stripped named destination identifier or false in case of error. + * @param string $name Destination name. + * @param float $y Y position in user units of the destiantion on the selected page (default = -1 = current position; 0 = page start;). + * @param int|string $page Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. + * @param float $x X position in user units of the destiantion on the selected page (default = -1 = current position;). + * @return string|false Stripped named destination identifier or false in case of error. * @public * @author Christian Deligant, Nicola Asuni * @since 5.9.097 (2011-06-23) @@ -12298,7 +12356,7 @@ class TCPDF { /** * Return the Named Destination array. - * @return (array) Named Destination array. + * @return array Named Destination array. * @public * @author Nicola Asuni * @since 5.9.097 (2011-06-23) @@ -12329,14 +12387,14 @@ class TCPDF { /** * Adds a bookmark - alias for Bookmark(). - * @param $txt (string) Bookmark description. - * @param $level (int) Bookmark level (minimum value is 0). - * @param $y (float) Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;). - * @param $page (int|string) Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. - * @param $style (string) Font style: B = Bold, I = Italic, BI = Bold + Italic. - * @param $color (array) RGB color array (values from 0 to 255). - * @param $x (float) X position in user units of the bookmark on the selected page (default = -1 = current position;). - * @param $link (mixed) URL, or numerical link ID, or named destination (# character followed by the destination name), or embedded file (* character followed by the file name). + * @param string $txt Bookmark description. + * @param int $level Bookmark level (minimum value is 0). + * @param float $y Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;). + * @param int|string $page Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. + * @param string $style Font style: B = Bold, I = Italic, BI = Bold + Italic. + * @param array $color RGB color array (values from 0 to 255). + * @param float $x X position in user units of the bookmark on the selected page (default = -1 = current position;). + * @param mixed $link URL, or numerical link ID, or named destination (# character followed by the destination name), or embedded file (* character followed by the file name). * @public */ public function setBookmark($txt, $level=0, $y=-1, $page='', $style='', $color=array(0,0,0), $x=-1, $link='') { @@ -12345,14 +12403,14 @@ class TCPDF { /** * Adds a bookmark. - * @param $txt (string) Bookmark description. - * @param $level (int) Bookmark level (minimum value is 0). - * @param $y (float) Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;). - * @param $page (int|string) Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. - * @param $style (string) Font style: B = Bold, I = Italic, BI = Bold + Italic. - * @param $color (array) RGB color array (values from 0 to 255). - * @param $x (float) X position in user units of the bookmark on the selected page (default = -1 = current position;). - * @param $link (mixed) URL, or numerical link ID, or named destination (# character followed by the destination name), or embedded file (* character followed by the file name). + * @param string $txt Bookmark description. + * @param int $level Bookmark level (minimum value is 0). + * @param float $y Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;). + * @param int|string $page Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. + * @param string $style Font style: B = Bold, I = Italic, BI = Bold + Italic. + * @param array $color RGB color array (values from 0 to 255). + * @param float $x X position in user units of the bookmark on the selected page (default = -1 = current position;). + * @param mixed $link URL, or numerical link ID, or named destination (# character followed by the destination name), or embedded file (* character followed by the file name). * @public * @since 2.1.002 (2008-02-12) */ @@ -12543,7 +12601,7 @@ class TCPDF { /** * Adds a javascript - * @param $script (string) Javascript code + * @param string $script Javascript code * @public * @author Johannes G\FCntert, Nicola Asuni * @since 2.1.002 (2008-02-12) @@ -12554,8 +12612,8 @@ class TCPDF { /** * Adds a javascript object and return object ID - * @param $script (string) Javascript code - * @param $onload (boolean) if true executes this object when opening the document + * @param string $script Javascript code + * @param boolean $onload if true executes this object when opening the document * @return int internal object ID * @public * @author Nicola Asuni @@ -12624,13 +12682,13 @@ class TCPDF { /** * Adds a javascript form field. - * @param $type (string) field type - * @param $name (string) field name - * @param $x (int) horizontal position - * @param $y (int) vertical position - * @param $w (int) width - * @param $h (int) height - * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. + * @param string $type field type + * @param string $name field name + * @param int $x horizontal position + * @param int $y vertical position + * @param int $w width + * @param int $h height + * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @protected * @author Denis Van Nuffelen, Nicola Asuni * @since 2.1.002 (2008-02-12) @@ -12666,7 +12724,7 @@ class TCPDF { /** * Set default properties for form fields. - * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. + * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-06) @@ -12688,23 +12746,23 @@ class TCPDF { /** * Creates a text field - * @param $name (string) field name - * @param $w (float) Width of the rectangle - * @param $h (float) Height of the rectangle - * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param $x (float) Abscissa of the upper-left corner of the rectangle - * @param $y (float) Ordinate of the upper-left corner of the rectangle - * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). + * @param string $name field name + * @param float $w Width of the rectangle + * @param float $h Height of the rectangle + * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. + * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. + * @param float|null $x Abscissa of the upper-left corner of the rectangle + * @param float|null $y Ordinate of the upper-left corner of the rectangle + * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ - public function TextField($name, $w, $h, $prop=array(), $opt=array(), $x='', $y='', $js=false) { - if ($x === '') { + public function TextField($name, $w, $h, $prop=array(), $opt=array(), $x=null, $y=null, $js=false) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -12808,24 +12866,24 @@ class TCPDF { /** * Creates a RadioButton field. - * @param $name (string) Field name. - * @param $w (int) Width of the radio button. - * @param $prop (array) Javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param $opt (array) Annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param $onvalue (string) Value to be returned if selected. - * @param $checked (boolean) Define the initial state. - * @param $x (float) Abscissa of the upper-left corner of the rectangle - * @param $y (float) Ordinate of the upper-left corner of the rectangle - * @param $js (boolean) If true put the field using JavaScript (requires Acrobat Writer to be rendered). + * @param string $name Field name. + * @param int $w Width of the radio button. + * @param array $prop Javascript field properties. Possible values are described on official Javascript for Acrobat API reference. + * @param array $opt Annotation parameters. Possible values are described on official PDF32000_2008 reference. + * @param string $onvalue Value to be returned if selected. + * @param boolean $checked Define the initial state. + * @param float|null $x Abscissa of the upper-left corner of the rectangle + * @param float|null $y Ordinate of the upper-left corner of the rectangle + * @param boolean $js If true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ - public function RadioButton($name, $w, $prop=array(), $opt=array(), $onvalue='On', $checked=false, $x='', $y='', $js=false) { - if ($x === '') { + public function RadioButton($name, $w, $prop=array(), $opt=array(), $onvalue='On', $checked=false, $x=null, $y=null, $js=false) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -12911,24 +12969,24 @@ class TCPDF { /** * Creates a List-box field - * @param $name (string) field name - * @param $w (int) width - * @param $h (int) height - * @param $values (array) array containing the list of values. - * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param $x (float) Abscissa of the upper-left corner of the rectangle - * @param $y (float) Ordinate of the upper-left corner of the rectangle - * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). + * @param string $name field name + * @param int $w width + * @param int $h height + * @param array $values array containing the list of values. + * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. + * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. + * @param float|null $x Abscissa of the upper-left corner of the rectangle + * @param float|null $y Ordinate of the upper-left corner of the rectangle + * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ - public function ListBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x='', $y='', $js=false) { - if ($x === '') { + public function ListBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x=null, $y=null, $js=false) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -12997,24 +13055,24 @@ class TCPDF { /** * Creates a Combo-box field - * @param $name (string) field name - * @param $w (int) width - * @param $h (int) height - * @param $values (array) array containing the list of values. - * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param $x (float) Abscissa of the upper-left corner of the rectangle - * @param $y (float) Ordinate of the upper-left corner of the rectangle - * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). + * @param string $name field name + * @param int $w width + * @param int $h height + * @param array $values array containing the list of values. + * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. + * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. + * @param float|null $x Abscissa of the upper-left corner of the rectangle + * @param float|null $y Ordinate of the upper-left corner of the rectangle + * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ - public function ComboBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x='', $y='', $js=false) { - if ($x === '') { + public function ComboBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x=null, $y=null, $js=false) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -13084,24 +13142,24 @@ class TCPDF { /** * Creates a CheckBox field - * @param $name (string) field name - * @param $w (int) width - * @param $checked (boolean) define the initial state. - * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param $onvalue (string) value to be returned if selected. - * @param $x (float) Abscissa of the upper-left corner of the rectangle - * @param $y (float) Ordinate of the upper-left corner of the rectangle - * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). + * @param string $name field name + * @param int $w width + * @param boolean $checked define the initial state. + * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. + * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. + * @param string $onvalue value to be returned if selected. + * @param float|null $x Abscissa of the upper-left corner of the rectangle + * @param float|null $y Ordinate of the upper-left corner of the rectangle + * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ - public function CheckBox($name, $w, $checked=false, $prop=array(), $opt=array(), $onvalue='Yes', $x='', $y='', $js=false) { - if ($x === '') { + public function CheckBox($name, $w, $checked=false, $prop=array(), $opt=array(), $onvalue='Yes', $x=null, $y=null, $js=false) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -13163,25 +13221,25 @@ class TCPDF { /** * Creates a button field - * @param $name (string) field name - * @param $w (int) width - * @param $h (int) height - * @param $caption (string) caption. - * @param $action (mixed) action triggered by pressing the button. Use a string to specify a javascript action. Use an array to specify a form action options as on section 12.7.5 of PDF32000_2008. - * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param $x (float) Abscissa of the upper-left corner of the rectangle - * @param $y (float) Ordinate of the upper-left corner of the rectangle - * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). + * @param string $name field name + * @param int $w width + * @param int $h height + * @param string $caption caption. + * @param mixed $action action triggered by pressing the button. Use a string to specify a javascript action. Use an array to specify a form action options as on section 12.7.5 of PDF32000_2008. + * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. + * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. + * @param float|null $x Abscissa of the upper-left corner of the rectangle + * @param float|null $y Ordinate of the upper-left corner of the rectangle + * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ - public function Button($name, $w, $h, $caption, $action, $prop=array(), $opt=array(), $x='', $y='', $js=false) { - if ($x === '') { + public function Button($name, $w, $h, $caption, $action, $prop=array(), $opt=array(), $x=null, $y=null, $js=false) { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -13214,7 +13272,7 @@ class TCPDF { 'R' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(51)), 'T' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(231)), 'B' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(51))); - $this->SetFillColor(204); + $this->setFillColor(204); $this->Cell($w, $h, $caption, $border, 0, 'C', true, '', 1, false, 'T', 'M'); $this->endTemplate(); --$this->n; @@ -13420,14 +13478,14 @@ class TCPDF { * WARNING: This is experimental and currently do not work. * Check the PDF Reference 8.7.1 Transform Methods, * Table 8.105 Entries in the UR transform parameters dictionary - * @param $enable (boolean) if true enable user's rights on PDF reader - * @param $document (string) Names specifying additional document-wide usage rights for the document. The only defined value is "/FullSave", which permits a user to save the document along with modified form and/or annotation data. - * @param $annots (string) Names specifying additional annotation-related usage rights for the document. Valid names in PDF 1.5 and later are /Create/Delete/Modify/Copy/Import/Export, which permit the user to perform the named operation on annotations. - * @param $form (string) Names specifying additional form-field-related usage rights for the document. Valid names are: /Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate - * @param $signature (string) Names specifying additional signature-related usage rights for the document. The only defined value is /Modify, which permits a user to apply a digital signature to an existing signature form field or clear a signed signature form field. - * @param $ef (string) Names specifying additional usage rights for named embedded files in the document. Valid names are /Create/Delete/Modify/Import, which permit the user to perform the named operation on named embedded files + * @param boolean $enable if true enable user's rights on PDF reader + * @param string $document Names specifying additional document-wide usage rights for the document. The only defined value is "/FullSave", which permits a user to save the document along with modified form and/or annotation data. + * @param string $annots Names specifying additional annotation-related usage rights for the document. Valid names in PDF 1.5 and later are /Create/Delete/Modify/Copy/Import/Export, which permit the user to perform the named operation on annotations. + * @param string $form Names specifying additional form-field-related usage rights for the document. Valid names are: /Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate + * @param string $signature Names specifying additional signature-related usage rights for the document. The only defined value is /Modify, which permits a user to apply a digital signature to an existing signature form field or clear a signed signature form field. + * @param string $ef Names specifying additional usage rights for named embedded files in the document. Valid names are /Create/Delete/Modify/Import, which permit the user to perform the named operation on named embedded files Names specifying additional embedded-files-related usage rights for the document. - * @param $formex (string) Names specifying additional form-field-related usage rights. The only valid name is BarcodePlaintext, which permits text form field data to be encoded as a plaintext two-dimensional barcode. + * @param string $formex Names specifying additional form-field-related usage rights. The only valid name is BarcodePlaintext, which permits text form field data to be encoded as a plaintext two-dimensional barcode. * @public * @author Nicola Asuni * @since 2.9.000 (2008-03-26) @@ -13458,13 +13516,13 @@ class TCPDF { * To create self-signed signature: openssl req -x509 -nodes -days 365000 -newkey rsa:1024 -keyout tcpdf.crt -out tcpdf.crt * To export crt to p12: openssl pkcs12 -export -in tcpdf.crt -out tcpdf.p12 * To convert pfx certificate to pem: openssl pkcs12 -in tcpdf.pfx -out tcpdf.crt -nodes - * @param $signing_cert (mixed) signing certificate (string or filename prefixed with 'file://') - * @param $private_key (mixed) private key (string or filename prefixed with 'file://') - * @param $private_key_password (string) password - * @param $extracerts (string) specifies the name of a file containing a bunch of extra certificates to include in the signature which can for example be used to help the recipient to verify the certificate that you used. - * @param $cert_type (int) The access permissions granted for this document. Valid values shall be: 1 = No changes to the document shall be permitted; any change to the document shall invalidate the signature; 2 = Permitted changes shall be filling in forms, instantiating page templates, and signing; other changes shall invalidate the signature; 3 = Permitted changes shall be the same as for 2, as well as annotation creation, deletion, and modification; other changes shall invalidate the signature. - * @param $info (array) array of option information: Name, Location, Reason, ContactInfo. - * @param $approval (string) Enable approval signature eg. for PDF incremental update + * @param mixed $signing_cert signing certificate (string or filename prefixed with 'file://') + * @param mixed $private_key private key (string or filename prefixed with 'file://') + * @param string $private_key_password password + * @param string $extracerts specifies the name of a file containing a bunch of extra certificates to include in the signature which can for example be used to help the recipient to verify the certificate that you used. + * @param int $cert_type The access permissions granted for this document. Valid values shall be: 1 = No changes to the document shall be permitted; any change to the document shall invalidate the signature; 2 = Permitted changes shall be filling in forms, instantiating page templates, and signing; other changes shall invalidate the signature; 3 = Permitted changes shall be the same as for 2, as well as annotation creation, deletion, and modification; other changes shall invalidate the signature. + * @param array $info array of option information: Name, Location, Reason, ContactInfo. + * @param string $approval Enable approval signature eg. for PDF incremental update * @public * @author Nicola Asuni * @since 4.6.005 (2009-04-24) @@ -13496,12 +13554,12 @@ class TCPDF { /** * Set the digital signature appearance (a cliccable rectangle area to get signature properties) - * @param $x (float) Abscissa of the upper-left corner. - * @param $y (float) Ordinate of the upper-left corner. - * @param $w (float) Width of the signature area. - * @param $h (float) Height of the signature area. - * @param $page (int) option page number (if < 0 the current page is used). - * @param $name (string) Name of the signature. + * @param float $x Abscissa of the upper-left corner. + * @param float $y Ordinate of the upper-left corner. + * @param float $w Width of the signature area. + * @param float $h Height of the signature area. + * @param int $page option page number (if < 0 the current page is used). + * @param string $name Name of the signature. * @public * @author Nicola Asuni * @since 5.3.011 (2010-06-17) @@ -13512,12 +13570,12 @@ class TCPDF { /** * Add an empty digital signature appearance (a cliccable rectangle area to get signature properties) - * @param $x (float) Abscissa of the upper-left corner. - * @param $y (float) Ordinate of the upper-left corner. - * @param $w (float) Width of the signature area. - * @param $h (float) Height of the signature area. - * @param $page (int) option page number (if < 0 the current page is used). - * @param $name (string) Name of the signature. + * @param float $x Abscissa of the upper-left corner. + * @param float $y Ordinate of the upper-left corner. + * @param float $w Width of the signature area. + * @param float $h Height of the signature area. + * @param int $page option page number (if < 0 the current page is used). + * @param string $name Name of the signature. * @public * @author Nicola Asuni * @since 5.9.101 (2011-07-06) @@ -13529,13 +13587,13 @@ class TCPDF { /** * Get the array that defines the signature appearance (page and rectangle coordinates). - * @param $x (float) Abscissa of the upper-left corner. - * @param $y (float) Ordinate of the upper-left corner. - * @param $w (float) Width of the signature area. - * @param $h (float) Height of the signature area. - * @param $page (int) option page number (if < 0 the current page is used). - * @param $name (string) Name of the signature. - * @return (array) Array defining page and rectangle coordinates of signature appearance. + * @param float $x Abscissa of the upper-left corner. + * @param float $y Ordinate of the upper-left corner. + * @param float $w Width of the signature area. + * @param float $h Height of the signature area. + * @param int $page option page number (if < 0 the current page is used). + * @param string $name Name of the signature. + * @return array Array defining page and rectangle coordinates of signature appearance. * @protected * @author Nicola Asuni * @since 5.9.101 (2011-07-06) @@ -13564,10 +13622,10 @@ class TCPDF { * Enable document timestamping (requires the OpenSSL Library). * The trusted timestamping improve document security that means that no one should be able to change the document once it has been recorded. * Use with digital signature only! - * @param $tsa_host (string) Time Stamping Authority (TSA) server (prefixed with 'https://') - * @param $tsa_username (string) Specifies the username for TSA authorization (optional) OR specifies the TSA authorization PEM file (see: example_66.php, optional) - * @param $tsa_password (string) Specifies the password for TSA authorization (optional) - * @param $tsa_cert (string) Specifies the location of TSA certificate for authorization (optional for cURL) + * @param string $tsa_host Time Stamping Authority (TSA) server (prefixed with 'https://') + * @param string $tsa_username Specifies the username for TSA authorization (optional) OR specifies the TSA authorization PEM file (see: example_66.php, optional) + * @param string $tsa_password Specifies the password for TSA authorization (optional) + * @param string $tsa_cert Specifies the location of TSA certificate for authorization (optional for cURL) * @public * @author Richard Stockinger * @since 6.0.090 (2014-06-16) @@ -13594,8 +13652,8 @@ class TCPDF { /** * NOT YET IMPLEMENTED * Request TSA for a timestamp - * @param $signature (string) Digital signature as binary string - * @return (string) Timestamped digital signature + * @param string $signature Digital signature as binary string + * @return string Timestamped digital signature * @protected * @author Richard Stockinger * @since 6.0.090 (2014-06-16) @@ -13611,11 +13669,11 @@ class TCPDF { /** * Create a new page group. * NOTE: call this function before calling AddPage() - * @param $page (int) starting group page (leave empty for next page). + * @param int|null $page starting group page (leave empty for next page). * @public * @since 3.0.000 (2008-03-27) */ - public function startPageGroup($page='') { + public function startPageGroup($page=null) { if (empty($page)) { $page = $this->page + 1; } @@ -13624,7 +13682,7 @@ class TCPDF { /** * Set the starting page number. - * @param $num (int) Starting page number. + * @param int $num Starting page number. * @since 5.9.093 (2011-06-16) * @public */ @@ -13691,7 +13749,7 @@ class TCPDF { * Return the alias for the total number of pages in the current page group. * If the current font is unicode type, the returned string is surrounded by additional curly braces. * This alias will be replaced by the total number of pages in this group. - * @return alias of the current page group + * @return string alias of the current page group * @public * @since 3.0.000 (2008-03-27) */ @@ -13706,7 +13764,7 @@ class TCPDF { * Return the alias for the page number on the current page group. * If the current font is unicode type, the returned string is surrounded by additional curly braces. * This alias will be replaced by the page number (relative to the belonging group). - * @return alias of the current page group + * @return string alias of the current page group * @public * @since 4.5.000 (2009-01-02) */ @@ -13719,7 +13777,7 @@ class TCPDF { /** * Return the current page in the group. - * @return current page in the group + * @return int current page in the group * @public * @since 3.0.000 (2008-03-27) */ @@ -13773,10 +13831,10 @@ class TCPDF { /** * Start a new pdf layer. - * @param $name (string) Layer name (only a-z letters and numbers). Leave empty for automatic name. - * @param $print (boolean|null) Set to TRUE to print this layer, FALSE to not print and NULL to not set this option - * @param $view (boolean) Set to true to view this layer. - * @param $lock (boolean) If true lock the layer + * @param string $name Layer name (only a-z letters and numbers). Leave empty for automatic name. + * @param boolean|null $print Set to TRUE to print this layer, FALSE to not print and NULL to not set this option + * @param boolean $view Set to true to view this layer. + * @param boolean $lock If true lock the layer * @public * @since 5.9.102 (2011-07-13) */ @@ -13815,7 +13873,7 @@ class TCPDF { * Set the visibility of the successive elements. * This can be useful, for instance, to put a background * image or color that will show on screen but won't print. - * @param $v (string) visibility mode. Legal values are: all, print, screen or view. + * @param string $v visibility mode. Legal values are: all, print, screen or view. * @public * @since 3.0.000 (2008-03-27) */ @@ -13847,13 +13905,13 @@ class TCPDF { /** * Add transparency parameters to the current extgstate - * @param $parms (array) parameters - * @return the number of extgstates + * @param array $parms parameters + * @return int|void the number of extgstates * @protected * @since 3.0.000 (2008-03-27) */ protected function addExtGState($parms) { - if ($this->pdfa_mode) { + if ($this->pdfa_mode || $this->pdfa_version >= 2) { // transparencies are not allowed in PDF/A mode return; } @@ -13879,13 +13937,13 @@ class TCPDF { /** * Add an extgstate - * @param $gs (array) extgstate + * @param int $gs extgstate * @protected * @since 3.0.000 (2008-03-27) */ protected function setExtGState($gs) { - if ($this->pdfa_mode OR ($this->state != 2)) { - // transparency is not allowed in PDF/A mode + if (($this->pdfa_mode && $this->pdfa_version < 2) OR ($this->state != 2)) { + // transparency is not allowed in PDF/A-1 mode return; } $this->_out(sprintf('/GS%d gs', $gs)); @@ -13919,13 +13977,13 @@ class TCPDF { /** * Set overprint mode for stroking (OP) and non-stroking (op) painting operations. * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008). - * @param $stroking (boolean) If true apply overprint for stroking operations. - * @param $nonstroking (boolean) If true apply overprint for painting operations other than stroking. - * @param $mode (integer) Overprint mode: (0 = each source colour component value replaces the value previously painted for the corresponding device colorant; 1 = a tint value of 0.0 for a source colour component shall leave the corresponding component of the previously painted colour unchanged). + * @param boolean $stroking If true apply overprint for stroking operations. + * @param boolean|null $nonstroking If true apply overprint for painting operations other than stroking. + * @param integer $mode Overprint mode: (0 = each source colour component value replaces the value previously painted for the corresponding device colorant; 1 = a tint value of 0.0 for a source colour component shall leave the corresponding component of the previously painted colour unchanged). * @public * @since 5.9.152 (2012-03-23) */ - public function setOverprint($stroking=true, $nonstroking='', $mode=0) { + public function setOverprint($stroking=true, $nonstroking=null, $mode=0) { if ($this->state != 2) { return; } @@ -13947,7 +14005,7 @@ class TCPDF { /** * Get the overprint mode array (OP, op, OPM). * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008). - * @return array. + * @return array * @public * @since 5.9.152 (2012-03-23) */ @@ -13957,16 +14015,16 @@ class TCPDF { /** * Set alpha for stroking (CA) and non-stroking (ca) operations. - * @param $stroking (float) Alpha value for stroking operations: real value from 0 (transparent) to 1 (opaque). - * @param $bm (string) blend mode, one of the following: Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity - * @param $nonstroking (float) Alpha value for non-stroking operations: real value from 0 (transparent) to 1 (opaque). - * @param $ais (boolean) + * @param float $stroking Alpha value for stroking operations: real value from 0 (transparent) to 1 (opaque). + * @param string $bm blend mode, one of the following: Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity + * @param float|null $nonstroking Alpha value for non-stroking operations: real value from 0 (transparent) to 1 (opaque). + * @param boolean $ais * @public * @since 3.0.000 (2008-03-27) */ - public function setAlpha($stroking=1, $bm='Normal', $nonstroking='', $ais=false) { - if ($this->pdfa_mode) { - // transparency is not allowed in PDF/A mode + public function setAlpha($stroking=1, $bm='Normal', $nonstroking=null, $ais=false) { + if ($this->pdfa_mode && $this->pdfa_version < 2) { + // transparency is not allowed in PDF/A-1 mode return; } $stroking = floatval($stroking); @@ -13992,7 +14050,7 @@ class TCPDF { /** * Get the alpha mode array (CA, ca, BM, AIS). * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008). - * @return array. + * @return array * @public * @since 5.9.152 (2012-03-23) */ @@ -14002,7 +14060,7 @@ class TCPDF { /** * Set the default JPEG compression quality (1-100) - * @param $quality (int) JPEG quality, integer between 1 and 100 + * @param int $quality JPEG quality, integer between 1 and 100 * @public * @since 3.0.000 (2008-03-27) */ @@ -14015,7 +14073,7 @@ class TCPDF { /** * Set the default number of columns in a row for HTML tables. - * @param $cols (int) number of columns + * @param int $cols number of columns * @public * @since 3.0.014 (2008-06-04) */ @@ -14025,7 +14083,7 @@ class TCPDF { /** * Set the height of the cell (line height) respect the font height. - * @param $h (int) cell proportion respect font height (typical value = 1.25). + * @param float $h cell proportion respect font height (typical value = 1.25). * @public * @since 3.0.014 (2008-06-04) */ @@ -14036,6 +14094,7 @@ class TCPDF { /** * return the height of cell repect font height. * @public + * @return float * @since 4.0.012 (2008-07-24) */ public function getCellHeightRatio() { @@ -14044,15 +14103,18 @@ class TCPDF { /** * Set the PDF version (check PDF reference for valid values). - * @param $version (string) PDF document version. + * @param string $version PDF document version. * @public * @since 3.1.000 (2008-06-09) */ public function setPDFVersion($version='1.7') { if ($this->pdfa_mode && $this->pdfa_version == 1 ) { - // PDF/A mode + // PDF/A-1 mode $this->PDFVersion = '1.4'; - } else { + } elseif ($this->pdfa_mode && $this->pdfa_version >= 2 ) { + // PDF/A-2 mode + $this->PDFVersion = '1.7'; + } else { $this->PDFVersion = $version; } } @@ -14061,7 +14123,7 @@ class TCPDF { * Set the viewer preferences dictionary controlling the way the document is to be presented on the screen or in print. * (see Section 8.1 of PDF reference, "Viewer Preferences"). *
              • HideToolbar boolean (Optional) A flag specifying whether to hide the viewer application's tool bars when the document is active. Default value: false.
              • HideMenubar boolean (Optional) A flag specifying whether to hide the viewer application's menu bar when the document is active. Default value: false.
              • HideWindowUI boolean (Optional) A flag specifying whether to hide user interface elements in the document's window (such as scroll bars and navigation controls), leaving only the document's contents displayed. Default value: false.
              • FitWindow boolean (Optional) A flag specifying whether to resize the document's window to fit the size of the first displayed page. Default value: false.
              • CenterWindow boolean (Optional) A flag specifying whether to position the document's window in the center of the screen. Default value: false.
              • DisplayDocTitle boolean (Optional; PDF 1.4) A flag specifying whether the window's title bar should display the document title taken from the Title entry of the document information dictionary (see Section 10.2.1, "Document Information Dictionary"). If false, the title bar should instead display the name of the PDF file containing the document. Default value: false.
              • NonFullScreenPageMode name (Optional) The document's page mode, specifying how to display the document on exiting full-screen mode:
                • UseNone Neither document outline nor thumbnail images visible
                • UseOutlines Document outline visible
                • UseThumbs Thumbnail images visible
                • UseOC Optional content group panel visible
                This entry is meaningful only if the value of the PageMode entry in the catalog dictionary (see Section 3.6.1, "Document Catalog") is FullScreen; it is ignored otherwise. Default value: UseNone.
              • ViewArea name (Optional; PDF 1.4) The name of the page boundary representing the area of a page to be displayed when viewing the document on the screen. Valid values are (see Section 10.10.1, "Page Boundaries").:
                • MediaBox
                • CropBox (default)
                • BleedBox
                • TrimBox
                • ArtBox
              • ViewClip name (Optional; PDF 1.4) The name of the page boundary to which the contents of a page are to be clipped when viewing the document on the screen. Valid values are (see Section 10.10.1, "Page Boundaries").:
                • MediaBox
                • CropBox (default)
                • BleedBox
                • TrimBox
                • ArtBox
              • PrintArea name (Optional; PDF 1.4) The name of the page boundary representing the area of a page to be rendered when printing the document. Valid values are (see Section 10.10.1, "Page Boundaries").:
                • MediaBox
                • CropBox (default)
                • BleedBox
                • TrimBox
                • ArtBox
              • PrintClip name (Optional; PDF 1.4) The name of the page boundary to which the contents of a page are to be clipped when printing the document. Valid values are (see Section 10.10.1, "Page Boundaries").:
                • MediaBox
                • CropBox (default)
                • BleedBox
                • TrimBox
                • ArtBox
              • PrintScaling name (Optional; PDF 1.6) The page scaling option to be selected when a print dialog is displayed for this document. Valid values are:
                • None, which indicates that the print dialog should reflect no page scaling
                • AppDefault (default), which indicates that applications should use the current print scaling
              • Duplex name (Optional; PDF 1.7) The paper handling option to use when printing the file from the print dialog. The following values are valid:
                • Simplex - Print single-sided
                • DuplexFlipShortEdge - Duplex and flip on the short edge of the sheet
                • DuplexFlipLongEdge - Duplex and flip on the long edge of the sheet
                Default value: none
              • PickTrayByPDFSize boolean (Optional; PDF 1.7) A flag specifying whether the PDF page size is used to select the input paper tray. This setting influences only the preset values used to populate the print dialog presented by a PDF viewer application. If PickTrayByPDFSize is true, the check box in the print dialog associated with input paper tray is checked. Note: This setting has no effect on Mac OS systems, which do not provide the ability to pick the input tray by size.
              • PrintPageRange array (Optional; PDF 1.7) The page numbers used to initialize the print dialog box when the file is printed. The first page of the PDF file is denoted by 1. Each pair consists of the first and last pages in the sub-range. An odd number of integers causes this entry to be ignored. Negative numbers cause the entire array to be ignored. Default value: as defined by PDF viewer application
              • NumCopies integer (Optional; PDF 1.7) The number of copies to be printed when the print dialog is opened for this file. Supported values are the integers 2 through 5. Values outside this range are ignored. Default value: as defined by PDF viewer application, but typically 1
              - * @param $preferences (array) array of options. + * @param array $preferences array of options. * @author Nicola Asuni * @public * @since 3.1.000 (2008-06-09) @@ -14072,13 +14134,13 @@ class TCPDF { /** * Paints color transition registration bars - * @param $x (float) abscissa of the top left corner of the rectangle. - * @param $y (float) ordinate of the top left corner of the rectangle. - * @param $w (float) width of the rectangle. - * @param $h (float) height of the rectangle. - * @param $transition (boolean) if true prints tcolor transitions to white. - * @param $vertical (boolean) if true prints bar vertically. - * @param $colors (string) colors to print separated by comma. Valid values are: A,W,R,G,B,C,M,Y,K,RGB,CMYK,ALL,ALLSPOT,. Where: A = grayscale black, W = grayscale white, R = RGB red, G RGB green, B RGB blue, C = CMYK cyan, M = CMYK magenta, Y = CMYK yellow, K = CMYK key/black, RGB = RGB registration color, CMYK = CMYK registration color, ALL = Spot registration color, ALLSPOT = print all defined spot colors, = name of the spot color to print. + * @param float $x abscissa of the top left corner of the rectangle. + * @param float $y ordinate of the top left corner of the rectangle. + * @param float $w width of the rectangle. + * @param float $h height of the rectangle. + * @param boolean $transition if true prints tcolor transitions to white. + * @param boolean $vertical if true prints bar vertically. + * @param string $colors colors to print separated by comma. Valid values are: A,W,R,G,B,C,M,Y,K,RGB,CMYK,ALL,ALLSPOT,. Where: A = grayscale black, W = grayscale white, R = RGB red, G RGB green, B RGB blue, C = CMYK cyan, M = CMYK magenta, Y = CMYK yellow, K = CMYK key/black, RGB = RGB registration color, CMYK = CMYK registration color, ALL = Spot registration color, ALLSPOT = print all defined spot colors, = name of the spot color to print. * @author Nicola Asuni * @since 4.9.000 (2010-03-26) * @public @@ -14201,7 +14263,7 @@ class TCPDF { // color gradient $this->LinearGradient($xb, $yb, $wb, $hb, $col_a, $col_b, $coords); } else { - $this->SetFillColorArray($col_b); + $this->setFillColorArray($col_b); // colored rectangle $this->Rect($xb, $yb, $wb, $hb, 'F', array()); } @@ -14213,18 +14275,18 @@ class TCPDF { /** * Paints crop marks. - * @param $x (float) abscissa of the crop mark center. - * @param $y (float) ordinate of the crop mark center. - * @param $w (float) width of the crop mark. - * @param $h (float) height of the crop mark. - * @param $type (string) type of crop mark, one symbol per type separated by comma: T = TOP, F = BOTTOM, L = LEFT, R = RIGHT, TL = A = TOP-LEFT, TR = B = TOP-RIGHT, BL = C = BOTTOM-LEFT, BR = D = BOTTOM-RIGHT. - * @param $color (array) crop mark color (default spot registration color). + * @param float $x abscissa of the crop mark center. + * @param float $y ordinate of the crop mark center. + * @param float $w width of the crop mark. + * @param float $h height of the crop mark. + * @param string $type type of crop mark, one symbol per type separated by comma: T = TOP, F = BOTTOM, L = LEFT, R = RIGHT, TL = A = TOP-LEFT, TR = B = TOP-RIGHT, BL = C = BOTTOM-LEFT, BR = D = BOTTOM-RIGHT. + * @param array $color crop mark color (default spot registration color). * @author Nicola Asuni * @since 4.9.000 (2010-03-26) * @public */ public function cropMark($x, $y, $w, $h, $type='T,R,B,L', $color=array(100,100,100,100,'All')) { - $this->SetLineStyle(array('width' => (0.5 / $this->k), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $color)); + $this->setLineStyle(array('width' => (0.5 / $this->k), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $color)); $type = strtoupper($type); $type = preg_replace('/[^A-Z\-\,]*/', '', $type); // split type in single components @@ -14284,28 +14346,28 @@ class TCPDF { /** * Paints a registration mark - * @param $x (float) abscissa of the registration mark center. - * @param $y (float) ordinate of the registration mark center. - * @param $r (float) radius of the crop mark. - * @param $double (boolean) if true print two concentric crop marks. - * @param $cola (array) crop mark color (default spot registration color 'All'). - * @param $colb (array) second crop mark color (default spot registration color 'None'). + * @param float $x abscissa of the registration mark center. + * @param float $y ordinate of the registration mark center. + * @param float $r radius of the crop mark. + * @param boolean $double if true print two concentric crop marks. + * @param array $cola crop mark color (default spot registration color 'All'). + * @param array $colb second crop mark color (default spot registration color 'None'). * @author Nicola Asuni * @since 4.9.000 (2010-03-26) * @public */ public function registrationMark($x, $y, $r, $double=false, $cola=array(100,100,100,100,'All'), $colb=array(0,0,0,0,'None')) { $line_style = array('width' => max((0.5 / $this->k),($r / 30)), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $cola); - $this->SetFillColorArray($cola); + $this->setFillColorArray($cola); $this->PieSector($x, $y, $r, 90, 180, 'F'); $this->PieSector($x, $y, $r, 270, 360, 'F'); $this->Circle($x, $y, $r, 0, 360, 'C', $line_style, array(), 8); if ($double) { $ri = $r * 0.5; - $this->SetFillColorArray($colb); + $this->setFillColorArray($colb); $this->PieSector($x, $y, $ri, 90, 180, 'F'); $this->PieSector($x, $y, $ri, 270, 360, 'F'); - $this->SetFillColorArray($cola); + $this->setFillColorArray($cola); $this->PieSector($x, $y, $ri, 0, 90, 'F'); $this->PieSector($x, $y, $ri, 180, 270, 'F'); $this->Circle($x, $y, $ri, 0, 360, 'C', $line_style, array(), 8); @@ -14314,9 +14376,9 @@ class TCPDF { /** * Paints a CMYK registration mark - * @param $x (float) abscissa of the registration mark center. - * @param $y (float) ordinate of the registration mark center. - * @param $r (float) radius of the crop mark. + * @param float $x abscissa of the registration mark center. + * @param float $y ordinate of the registration mark center. + * @param float $r radius of the crop mark. * @author Nicola Asuni * @since 6.0.038 (2013-09-30) * @public @@ -14329,20 +14391,20 @@ class TCPDF { // external radius $re = ($r * 1.3); // Cyan - $this->SetFillColorArray(array(100,0,0,0)); + $this->setFillColorArray(array(100,0,0,0)); $this->PieSector($x, $y, $ri, 270, 360, 'F'); // Magenta - $this->SetFillColorArray(array(0,100,0,0)); + $this->setFillColorArray(array(0,100,0,0)); $this->PieSector($x, $y, $ri, 0, 90, 'F'); // Yellow - $this->SetFillColorArray(array(0,0,100,0)); + $this->setFillColorArray(array(0,0,100,0)); $this->PieSector($x, $y, $ri, 90, 180, 'F'); // Key - black - $this->SetFillColorArray(array(0,0,0,100)); + $this->setFillColorArray(array(0,0,0,100)); $this->PieSector($x, $y, $ri, 180, 270, 'F'); // registration color $line_style = array('width' => $lw, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(100,100,100,100,'All')); - $this->SetFillColorArray(array(100,100,100,100,'All')); + $this->setFillColorArray(array(100,100,100,100,'All')); // external circle $this->Circle($x, $y, $r, 0, 360, 'C', $line_style, array(), 8); // cross lines @@ -14354,13 +14416,13 @@ class TCPDF { /** * Paints a linear colour gradient. - * @param $x (float) abscissa of the top left corner of the rectangle. - * @param $y (float) ordinate of the top left corner of the rectangle. - * @param $w (float) width of the rectangle. - * @param $h (float) height of the rectangle. - * @param $col1 (array) first color (Grayscale, RGB or CMYK components). - * @param $col2 (array) second color (Grayscale, RGB or CMYK components). - * @param $coords (array) array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg). The default value is from left to right (x1=0, y1=0, x2=1, y2=0). + * @param float $x abscissa of the top left corner of the rectangle. + * @param float $y ordinate of the top left corner of the rectangle. + * @param float $w width of the rectangle. + * @param float $h height of the rectangle. + * @param array $col1 first color (Grayscale, RGB or CMYK components). + * @param array $col2 second color (Grayscale, RGB or CMYK components). + * @param array $coords array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg). The default value is from left to right (x1=0, y1=0, x2=1, y2=0). * @author Andreas W\FCrmser, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public @@ -14372,13 +14434,13 @@ class TCPDF { /** * Paints a radial colour gradient. - * @param $x (float) abscissa of the top left corner of the rectangle. - * @param $y (float) ordinate of the top left corner of the rectangle. - * @param $w (float) width of the rectangle. - * @param $h (float) height of the rectangle. - * @param $col1 (array) first color (Grayscale, RGB or CMYK components). - * @param $col2 (array) second color (Grayscale, RGB or CMYK components). - * @param $coords (array) array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1, (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg). (fx, fy) should be inside the circle, otherwise some areas will not be defined. + * @param float $x abscissa of the top left corner of the rectangle. + * @param float $y ordinate of the top left corner of the rectangle. + * @param float $w width of the rectangle. + * @param float $h height of the rectangle. + * @param array $col1 first color (Grayscale, RGB or CMYK components). + * @param array $col2 second color (Grayscale, RGB or CMYK components). + * @param array $coords array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1, (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg). (fx, fy) should be inside the circle, otherwise some areas will not be defined. * @author Andreas W\FCrmser, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public @@ -14390,24 +14452,24 @@ class TCPDF { /** * Paints a coons patch mesh. - * @param $x (float) abscissa of the top left corner of the rectangle. - * @param $y (float) ordinate of the top left corner of the rectangle. - * @param $w (float) width of the rectangle. - * @param $h (float) height of the rectangle. - * @param $col1 (array) first color (lower left corner) (RGB components). - * @param $col2 (array) second color (lower right corner) (RGB components). - * @param $col3 (array) third color (upper right corner) (RGB components). - * @param $col4 (array) fourth color (upper left corner) (RGB components). - * @param $coords (array)
              • for one patch mesh: array(float x1, float y1, .... float x12, float y12): 12 pairs of coordinates (normally from 0 to 1) which specify the Bezier control points that define the patch. First pair is the lower left edge point, next is its right control point (control point 2). Then the other points are defined in the order: control point 1, edge point, control point 2 going counter-clockwise around the patch. Last (x12, y12) is the first edge point's left control point (control point 1).
              • for two or more patch meshes: array[number of patches]: arrays with the following keys for each patch: f: where to put that patch (0 = first patch, 1, 2, 3 = right, top and left of precedent patch - I didn't figure this out completely - just try and error ;-) points: 12 pairs of coordinates of the Bezier control points as above for the first patch, 8 pairs of coordinates for the following patches, ignoring the coordinates already defined by the precedent patch (I also didn't figure out the order of these - also: try and see what's happening) colors: must be 4 colors for the first patch, 2 colors for the following patches
              - * @param $coords_min (array) minimum value used by the coordinates. If a coordinate's value is smaller than this it will be cut to coords_min. default: 0 - * @param $coords_max (array) maximum value used by the coordinates. If a coordinate's value is greater than this it will be cut to coords_max. default: 1 - * @param $antialias (boolean) A flag indicating whether to filter the shading function to prevent aliasing artifacts. + * @param float $x abscissa of the top left corner of the rectangle. + * @param float $y ordinate of the top left corner of the rectangle. + * @param float $w width of the rectangle. + * @param float $h height of the rectangle. + * @param array $col1 first color (lower left corner) (RGB components). + * @param array $col2 second color (lower right corner) (RGB components). + * @param array $col3 third color (upper right corner) (RGB components). + * @param array $col4 fourth color (upper left corner) (RGB components). + * @param array $coords
              • for one patch mesh: array(float x1, float y1, .... float x12, float y12): 12 pairs of coordinates (normally from 0 to 1) which specify the Bezier control points that define the patch. First pair is the lower left edge point, next is its right control point (control point 2). Then the other points are defined in the order: control point 1, edge point, control point 2 going counter-clockwise around the patch. Last (x12, y12) is the first edge point's left control point (control point 1).
              • for two or more patch meshes: array[number of patches]: arrays with the following keys for each patch: f: where to put that patch (0 = first patch, 1, 2, 3 = right, top and left of precedent patch - I didn't figure this out completely - just try and error ;-) points: 12 pairs of coordinates of the Bezier control points as above for the first patch, 8 pairs of coordinates for the following patches, ignoring the coordinates already defined by the precedent patch (I also didn't figure out the order of these - also: try and see what's happening) colors: must be 4 colors for the first patch, 2 colors for the following patches
              + * @param array $coords_min minimum value used by the coordinates. If a coordinate's value is smaller than this it will be cut to coords_min. default: 0 + * @param array $coords_max maximum value used by the coordinates. If a coordinate's value is greater than this it will be cut to coords_max. default: 1 + * @param boolean $antialias A flag indicating whether to filter the shading function to prevent aliasing artifacts. * @author Andreas W\FCrmser, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function CoonsPatchMesh($x, $y, $w, $h, $col1=array(), $col2=array(), $col3=array(), $col4=array(), $coords=array(0.00,0.0,0.33,0.00,0.67,0.00,1.00,0.00,1.00,0.33,1.00,0.67,1.00,1.00,0.67,1.00,0.33,1.00,0.00,1.00,0.00,0.67,0.00,0.33), $coords_min=0, $coords_max=1, $antialias=false) { - if ($this->pdfa_mode OR ($this->state != 2)) { + if (($this->pdfa_mode && $this->pdfa_version < 2) OR ($this->state != 2)) { return; } $this->Clip($x, $y, $w, $h); @@ -14467,8 +14529,8 @@ class TCPDF { if ($patch_array[$i]['points'][$j] > $bpcd) { $patch_array[$i]['points'][$j] = $bpcd; } - $this->gradients[$n]['stream'] .= chr(floor($patch_array[$i]['points'][$j] / 256)); - $this->gradients[$n]['stream'] .= chr(floor($patch_array[$i]['points'][$j] % 256)); + $this->gradients[$n]['stream'] .= chr((int) floor($patch_array[$i]['points'][$j] / 256)); + $this->gradients[$n]['stream'] .= chr((int) floor(intval($patch_array[$i]['points'][$j]) % 256)); } $count_cols = count($patch_array[$i]['colors']); for ($j=0; $j < $count_cols; ++$j) { @@ -14490,10 +14552,10 @@ class TCPDF { /** * Set a rectangular clipping area. - * @param $x (float) abscissa of the top left corner of the rectangle (or top right corner for RTL mode). - * @param $y (float) ordinate of the top left corner of the rectangle. - * @param $w (float) width of the rectangle. - * @param $h (float) height of the rectangle. + * @param float $x abscissa of the top left corner of the rectangle (or top right corner for RTL mode). + * @param float $y ordinate of the top left corner of the rectangle. + * @param float $w width of the rectangle. + * @param float $h height of the rectangle. * @author Andreas W\FCrmser, Nicola Asuni * @since 3.1.000 (2008-06-09) * @protected @@ -14516,17 +14578,17 @@ class TCPDF { /** * Output gradient. - * @param $type (int) type of gradient (1 Function-based shading; 2 Axial shading; 3 Radial shading; 4 Free-form Gouraud-shaded triangle mesh; 5 Lattice-form Gouraud-shaded triangle mesh; 6 Coons patch mesh; 7 Tensor-product patch mesh). (Not all types are currently supported) - * @param $coords (array) array of coordinates. - * @param $stops (array) array gradient color components: color = array of GRAY, RGB or CMYK color components; offset = (0 to 1) represents a location along the gradient vector; exponent = exponent of the exponential interpolation function (default = 1). - * @param $background (array) An array of colour components appropriate to the colour space, specifying a single background colour value. - * @param $antialias (boolean) A flag indicating whether to filter the shading function to prevent aliasing artifacts. + * @param int $type type of gradient (1 Function-based shading; 2 Axial shading; 3 Radial shading; 4 Free-form Gouraud-shaded triangle mesh; 5 Lattice-form Gouraud-shaded triangle mesh; 6 Coons patch mesh; 7 Tensor-product patch mesh). (Not all types are currently supported) + * @param array $coords array of coordinates. + * @param array $stops array gradient color components: color = array of GRAY, RGB or CMYK color components; offset = (0 to 1) represents a location along the gradient vector; exponent = exponent of the exponential interpolation function (default = 1). + * @param array $background An array of colour components appropriate to the colour space, specifying a single background colour value. + * @param boolean $antialias A flag indicating whether to filter the shading function to prevent aliasing artifacts. * @author Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function Gradient($type, $coords, $stops, $background=array(), $antialias=false) { - if ($this->pdfa_mode OR ($this->state != 2)) { + if (($this->pdfa_mode && $this->pdfa_version < 2) OR ($this->state != 2)) { return; } $n = count($this->gradients) + 1; @@ -14582,7 +14644,7 @@ class TCPDF { } if (isset($stop['opacity'])) { $this->gradients[$n]['colors'][$key]['opacity'] = $stop['opacity']; - if ((!$this->pdfa_mode) AND ($stop['opacity'] < 1)) { + if ((!($this->pdfa_mode && $this->pdfa_version < 2)) AND ($stop['opacity'] < 1)) { $this->gradients[$n]['transparency'] = true; } } else { @@ -14633,7 +14695,7 @@ class TCPDF { * @protected */ function _putshaders() { - if ($this->pdfa_mode) { + if ($this->pdfa_mode && $this->pdfa_version < 2) { return; } $idt = count($this->gradients); //index for transparency gradients @@ -14812,14 +14874,14 @@ class TCPDF { /** * Draw the sector of a circle. * It can be used for instance to render pie charts. - * @param $xc (float) abscissa of the center. - * @param $yc (float) ordinate of the center. - * @param $r (float) radius. - * @param $a (float) start angle (in degrees). - * @param $b (float) end angle (in degrees). - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $cw: (float) indicates whether to go clockwise (default: true). - * @param $o: (float) origin of angles (0 for 3 o'clock, 90 for noon, 180 for 9 o'clock, 270 for 6 o'clock). Default: 90. + * @param float $xc abscissa of the center. + * @param float $yc ordinate of the center. + * @param float $r radius. + * @param float $a start angle (in degrees). + * @param float $b end angle (in degrees). + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param float $cw indicates whether to go clockwise (default: true). + * @param float $o origin of angles (0 for 3 o'clock, 90 for noon, 180 for 9 o'clock, 270 for 6 o'clock). Default: 90. * @author Maxime Delorme, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public @@ -14831,16 +14893,16 @@ class TCPDF { /** * Draw the sector of an ellipse. * It can be used for instance to render pie charts. - * @param $xc (float) abscissa of the center. - * @param $yc (float) ordinate of the center. - * @param $rx (float) the x-axis radius. - * @param $ry (float) the y-axis radius. - * @param $a (float) start angle (in degrees). - * @param $b (float) end angle (in degrees). - * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. - * @param $cw: (float) indicates whether to go clockwise. - * @param $o: (float) origin of angles (0 for 3 o'clock, 90 for noon, 180 for 9 o'clock, 270 for 6 o'clock). - * @param $nc (integer) Number of curves used to draw a 90 degrees portion of arc. + * @param float $xc abscissa of the center. + * @param float $yc ordinate of the center. + * @param float $rx the x-axis radius. + * @param float $ry the y-axis radius. + * @param float $a start angle (in degrees). + * @param float $b end angle (in degrees). + * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. + * @param float $cw indicates whether to go clockwise. + * @param float $o origin of angles (0 for 3 o'clock, 90 for noon, 180 for 9 o'clock, 270 for 6 o'clock). + * @param integer $nc Number of curves used to draw a 90 degrees portion of arc. * @author Maxime Delorme, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public @@ -14873,23 +14935,23 @@ class TCPDF { * NOTE: EPS is not yet fully implemented, use the setRasterizeVectorImages() method to enable/disable rasterization of vector images using ImageMagick library. * Only vector drawing is supported, not text or bitmap. * Although the script was successfully tested with various AI format versions, best results are probably achieved with files that were exported in the AI3 format (tested with Illustrator CS2, Freehand MX and Photoshop CS2). - * @param $file (string) Name of the file containing the image or a '@' character followed by the EPS/AI data string. - * @param $x (float) Abscissa of the upper-left corner. - * @param $y (float) Ordinate of the upper-left corner. - * @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param $link (mixed) URL or identifier returned by AddLink(). - * @param $useBoundingBox (boolean) specifies whether to position the bounding box (true) or the complete canvas (false) at location (x,y). Default value is true. - * @param $align (string) Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
              • T: top-right for LTR or top-left for RTL
              • M: middle-right for LTR or middle-left for RTL
              • B: bottom-right for LTR or bottom-left for RTL
              • N: next line
              - * @param $palign (string) Allows to center or align the image on the current line. Possible values are:
              • L : left align
              • C : center
              • R : right align
              • '' : empty string : left for LTR or right for RTL
              - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param $fitonpage (boolean) if true the image is resized to not exceed page dimensions. - * @param $fixoutvals (boolean) if true remove values outside the bounding box. + * @param string $file Name of the file containing the image or a '@' character followed by the EPS/AI data string. + * @param float|null $x Abscissa of the upper-left corner. + * @param float|null $y Ordinate of the upper-left corner. + * @param float $w Width of the image in the page. If not specified or equal to zero, it is automatically calculated. + * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated. + * @param mixed $link URL or identifier returned by AddLink(). + * @param boolean $useBoundingBox specifies whether to position the bounding box (true) or the complete canvas (false) at location (x,y). Default value is true. + * @param string $align Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
              • T: top-right for LTR or top-left for RTL
              • M: middle-right for LTR or middle-left for RTL
              • B: bottom-right for LTR or bottom-left for RTL
              • N: next line
              + * @param string $palign Allows to center or align the image on the current line. Possible values are:
              • L : left align
              • C : center
              • R : right align
              • '' : empty string : left for LTR or right for RTL
              + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
              • 0: no border (default)
              • 1: frame
              or a string containing some or all of the following characters (in any order):
              • L: left
              • T: top
              • R: right
              • B: bottom
              or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param boolean $fitonpage if true the image is resized to not exceed page dimensions. + * @param boolean $fixoutvals if true remove values outside the bounding box. * @author Valentin Schmidt, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ - public function ImageEps($file, $x='', $y='', $w=0, $h=0, $link='', $useBoundingBox=true, $align='', $palign='', $border=0, $fitonpage=false, $fixoutvals=false) { + public function ImageEps($file, $x=null, $y=null, $w=0, $h=0, $link='', $useBoundingBox=true, $align='', $palign='', $border=0, $fitonpage=false, $fixoutvals=false) { if ($this->state != 2) { return; } @@ -14897,10 +14959,10 @@ class TCPDF { // convert EPS to raster image using GD or ImageMagick libraries return $this->Image($file, $x, $y, $w, $h, 'EPS', $link, $align, true, 300, $palign, false, false, $border, false, false, $fitonpage); } - if ($x === '') { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -14909,7 +14971,7 @@ class TCPDF { if ($file[0] === '@') { // image from string $data = substr($file, 1); } else { // EPS/AI file - $data = TCPDF_STATIC::fileGetContents($file); + $data = $this->getCachedFileContents($file); } if ($data === FALSE) { $this->Error('EPS file not found: '.$file); @@ -15193,7 +15255,7 @@ class TCPDF { break; } case 'N':{ - $this->SetY($this->img_rb_y); + $this->setY($this->img_rb_y); break; } default:{ @@ -15205,7 +15267,7 @@ class TCPDF { /** * Set document barcode. - * @param $bc (string) barcode + * @param string $bc barcode * @public */ public function setBarcode($bc='') { @@ -15224,14 +15286,14 @@ class TCPDF { /** * Print a Linear Barcode. - * @param $code (string) code to print - * @param $type (string) type of barcode (see tcpdf_barcodes_1d.php for supported formats). - * @param $x (int) x position in user units (empty string = current x position) - * @param $y (int) y position in user units (empty string = current y position) - * @param $w (int) width in user units (empty string = remaining page width) - * @param $h (int) height in user units (empty string = remaining page height) - * @param $xres (float) width of the smallest bar in user units (empty string = default value = 0.4mm) - * @param $style (array) array of options:
                + * @param string $code code to print + * @param string $type type of barcode (see tcpdf_barcodes_1d.php for supported formats). + * @param float|null $x x position in user units (null = current x position) + * @param float|null $y y position in user units (null = current y position) + * @param float|null $w width in user units (null = remaining page width) + * @param float|null $h height in user units (null = remaining page height) + * @param float|null $xres width of the smallest bar in user units (null = default value = 0.4mm) + * @param array $style array of options:
                  *
                • boolean $style['border'] if true prints a border
                • *
                • int $style['padding'] padding to leave around the barcode in user units (set to 'auto' for automatic padding)
                • *
                • int $style['hpadding'] horizontal padding in user units (set to 'auto' for automatic padding)
                • @@ -15247,12 +15309,12 @@ class TCPDF { *
                • string $style['stretch'] if true stretch the barcode to best fit the available width, otherwise uses $xres resolution for a single bar.
                • *
                • string $style['fitwidth'] if true reduce the width to fit the barcode width + padding. When this option is enabled the 'stretch' option is automatically disabled.
                • *
                • string $style['cellfitalign'] this option works only when 'fitwidth' is true and 'position' is unset or empty. Set the horizontal position of the containing barcode cell inside the specified rectangle: L = left; C = center; R = right.
                - * @param $align (string) Indicates the alignment of the pointer next to barcode insertion relative to barcode height. The value can be:
                • T: top-right for LTR or top-left for RTL
                • M: middle-right for LTR or middle-left for RTL
                • B: bottom-right for LTR or bottom-left for RTL
                • N: next line
                + * @param string $align Indicates the alignment of the pointer next to barcode insertion relative to barcode height. The value can be:
                • T: top-right for LTR or top-left for RTL
                • M: middle-right for LTR or middle-left for RTL
                • B: bottom-right for LTR or bottom-left for RTL
                • N: next line
                * @author Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ - public function write1DBarcode($code, $type, $x='', $y='', $w='', $h='', $xres='', $style=array(), $align='') { + public function write1DBarcode($code, $type, $x=null, $y=null, $w=null, $h=null, $xres=null, $style=array(), $align='') { if (TCPDF_STATIC::empty_string(trim($code))) { return; } @@ -15262,7 +15324,7 @@ class TCPDF { // create new barcode object $barcodeobj = new TCPDFBarcode($code, $type); $arrcode = $barcodeobj->getBarcodeArray(); - if (($arrcode === false) OR empty($arrcode) OR ($arrcode['maxw'] <= 0)) { + if (empty($arrcode) OR ($arrcode['maxw'] <= 0)) { $this->Error('Error in 1D barcode string'); } if ($arrcode['maxh'] <= 0) { @@ -15311,20 +15373,20 @@ class TCPDF { if (isset($style['fontsize'])) { $fontsize = $style['fontsize']; } - $this->SetFont($style['font'], '', $fontsize); + $this->setFont($style['font'], '', $fontsize); } if (!isset($style['stretchtext'])) { $style['stretchtext'] = 4; } - if ($x === '') { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); - if (($w === '') OR ($w <= 0)) { + if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) { if ($this->rtl) { $w = $x - $this->lMargin; } else { @@ -15408,7 +15470,7 @@ class TCPDF { } $text_height = $this->getCellHeight($fontsize / $this->k); // height - if (($h === '') OR ($h <= 0)) { + if (TCPDF_STATIC::empty_string($h) OR ($h <= 0)) { // set default height $h = (($arrcode['maxw'] * $xres) / 3) + (2 * $vpadding) + $text_height; } @@ -15418,7 +15480,7 @@ class TCPDF { if ($text_height > $h) { $fontsize = (($h * $this->k) / (4 * $this->cell_height_ratio)); $text_height = $this->getCellHeight($fontsize / $this->k); - $this->SetFont($style['font'], '', $fontsize); + $this->setFont($style['font'], '', $fontsize); } if ($vpadding > 0) { $vpadding = (($h - $text_height) / 4); @@ -15483,8 +15545,8 @@ class TCPDF { $this->Rect($xpos_rect, $y, $w, $h, 'D'); } // set foreground color - $this->SetDrawColorArray($style['fgcolor']); - $this->SetTextColorArray($style['fgcolor']); + $this->setDrawColorArray($style['fgcolor']); + $this->setTextColorArray($style['fgcolor']); // print bars foreach ($arrcode['bcode'] as $k => $v) { $bw = ($v['w'] * $xres); @@ -15510,8 +15572,8 @@ class TCPDF { $this->x = $xpos_text; $this->y = $y + $vpadding + $barh; $cellpadding = $this->cell_padding; - $this->SetCellPadding(0); - $this->Cell($txtwidth, '', $label, 0, 0, 'C', false, '', $style['stretchtext'], false, 'T', 'T'); + $this->setCellPadding(0); + $this->Cell($txtwidth, 0, $label, 0, 0, 'C', false, '', $style['stretchtext'], false, 'T', 'T'); $this->cell_padding = $cellpadding; } // restore original direction @@ -15536,7 +15598,7 @@ class TCPDF { break; } case 'N':{ - $this->SetY($this->img_rb_y); + $this->setY($this->img_rb_y); break; } default:{ @@ -15548,13 +15610,13 @@ class TCPDF { /** * Print 2D Barcode. - * @param $code (string) code to print - * @param $type (string) type of barcode (see tcpdf_barcodes_2d.php for supported formats). - * @param $x (int) x position in user units - * @param $y (int) y position in user units - * @param $w (int) width in user units - * @param $h (int) height in user units - * @param $style (array) array of options:
                  + * @param string $code code to print + * @param string $type type of barcode (see tcpdf_barcodes_2d.php for supported formats). + * @param float|null $x x position in user units + * @param float|null $y y position in user units + * @param float|null $w width in user units + * @param float|null $h height in user units + * @param array $style array of options:
                    *
                  • boolean $style['border'] if true prints a border around the barcode
                  • *
                  • int $style['padding'] padding to leave around the barcode in barcode units (set to 'auto' for automatic padding)
                  • *
                  • int $style['hpadding'] horizontal padding in barcode units (set to 'auto' for automatic padding)
                  • @@ -15564,13 +15626,13 @@ class TCPDF { *
                  • array $style['fgcolor'] color array for bars and text
                  • *
                  • mixed $style['bgcolor'] color array for background or false for transparent
                  • *
                  • string $style['position'] barcode position on the page: L = left margin; C = center; R = right margin; S = stretch
                  • - * @param $align (string) Indicates the alignment of the pointer next to barcode insertion relative to barcode height. The value can be:
                    • T: top-right for LTR or top-left for RTL
                    • M: middle-right for LTR or middle-left for RTL
                    • B: bottom-right for LTR or bottom-left for RTL
                    • N: next line
                    - * @param $distort (boolean) if true distort the barcode to fit width and height, otherwise preserve aspect ratio + * @param string $align Indicates the alignment of the pointer next to barcode insertion relative to barcode height. The value can be:
                    • T: top-right for LTR or top-left for RTL
                    • M: middle-right for LTR or middle-left for RTL
                    • B: bottom-right for LTR or bottom-left for RTL
                    • N: next line
                    + * @param boolean $distort if true distort the barcode to fit width and height, otherwise preserve aspect ratio * @author Nicola Asuni * @since 4.5.037 (2009-04-07) * @public */ - public function write2DBarcode($code, $type, $x='', $y='', $w='', $h='', $style=array(), $align='', $distort=false) { + public function write2DBarcode($code, $type, $x=null, $y=null, $w=null, $h=null, $style=array(), $align='', $distort=false) { if (TCPDF_STATIC::empty_string(trim($code))) { return; } @@ -15580,7 +15642,7 @@ class TCPDF { // create new barcode object $barcodeobj = new TCPDF2DBarcode($code, $type); $arrcode = $barcodeobj->getBarcodeArray(); - if (($arrcode === false) OR empty($arrcode) OR !isset($arrcode['num_rows']) OR ($arrcode['num_rows'] == 0) OR !isset($arrcode['num_cols']) OR ($arrcode['num_cols'] == 0)) { + if (empty($arrcode) OR !isset($arrcode['num_rows']) OR ($arrcode['num_rows'] == 0) OR !isset($arrcode['num_cols']) OR ($arrcode['num_cols'] == 0)) { $this->Error('Error in 2D barcode string'); } // set default values @@ -15621,10 +15683,10 @@ class TCPDF { if (!isset($style['module_height'])) { $style['module_height'] = 1; // height of a single module in points } - if ($x === '') { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -15666,7 +15728,7 @@ class TCPDF { $h = $maxh; } // set dimensions - if ((($w === '') OR ($w <= 0)) AND (($h === '') OR ($h <= 0))) { + if ((TCPDF_STATIC::empty_string($w) OR ($w <= 0)) AND (TCPDF_STATIC::empty_string($h) OR ($h <= 0))) { $w = ($cols + $hpad) * ($mw / $this->k); $h = ($rows + $vpad) * ($mh / $this->k); } elseif (($w === '') OR ($w <= 0)) { @@ -15733,7 +15795,7 @@ class TCPDF { $this->Rect($xpos, $y, $w, $h, 'D'); } // set foreground color - $this->SetDrawColorArray($style['fgcolor']); + $this->setDrawColorArray($style['fgcolor']); // print barcode cells // for each row for ($r = 0; $r < $rows; ++$r) { @@ -15770,7 +15832,7 @@ class TCPDF { break; } case 'N':{ - $this->SetY($this->img_rb_y); + $this->setY($this->img_rb_y); break; } default:{ @@ -15836,7 +15898,7 @@ class TCPDF { /** * Returns the current font size. - * @return current font size + * @return float current font size * @public * @since 3.2.000 (2008-06-23) */ @@ -15846,7 +15908,7 @@ class TCPDF { /** * Returns the current font size in points unit. - * @return current font size in points unit + * @return int current font size in points unit * @public * @since 3.2.000 (2008-06-23) */ @@ -15876,23 +15938,23 @@ class TCPDF { /** * Cleanup HTML code (requires HTML Tidy library). - * @param $html (string) htmlcode to fix - * @param $default_css (string) CSS commands to add - * @param $tagvs (array) parameters for setHtmlVSpace method - * @param $tidy_options (array) options for tidy_parse_string function + * @param string $html htmlcode to fix + * @param string $default_css CSS commands to add + * @param array|null $tagvs parameters for setHtmlVSpace method + * @param array|null $tidy_options options for tidy_parse_string function * @return string XHTML code cleaned up * @author Nicola Asuni * @public * @since 5.9.017 (2010-11-16) * @see setHtmlVSpace() */ - public function fixHTMLCode($html, $default_css='', $tagvs='', $tidy_options='') { + public function fixHTMLCode($html, $default_css='', $tagvs=null, $tidy_options=null) { return TCPDF_STATIC::fixHTMLCode($html, $default_css, $tagvs, $tidy_options, $this->tagvspaces); } /** * Returns the border width from CSS property - * @param $width (string) border width + * @param string $width border width * @return int with in user units * @protected * @since 5.7.000 (2010-08-02) @@ -15912,7 +15974,7 @@ class TCPDF { /** * Returns the border dash style from CSS property - * @param $style (string) border style to convert + * @param string $style border style to convert * @return int sash style (return -1 in case of none or hidden border) * @protected * @since 5.7.000 (2010-08-02) @@ -15948,7 +16010,7 @@ class TCPDF { /** * Returns the border style array from CSS border properties - * @param $cssborder (string) border properties + * @param string $cssborder border properties * @return array containing border properties * @protected * @since 5.7.000 (2010-08-02) @@ -15998,8 +16060,8 @@ class TCPDF { /** * Get the internal Cell padding from CSS attribute. - * @param $csspadding (string) padding properties - * @param $width (float) width of the containing element + * @param string $csspadding padding properties + * @param float $width width of the containing element * @return array of cell paddings * @public * @since 5.9.000 (2010-10-04) @@ -16052,8 +16114,8 @@ class TCPDF { /** * Get the internal Cell margin from CSS attribute. - * @param $cssmargin (string) margin properties - * @param $width (float) width of the containing element + * @param string $cssmargin margin properties + * @param float $width width of the containing element * @return array of cell margins * @public * @since 5.9.000 (2010-10-04) @@ -16106,8 +16168,8 @@ class TCPDF { /** * Get the border-spacing from CSS attribute. - * @param $cssbspace (string) border-spacing CSS properties - * @param $width (float) width of the containing element + * @param string $cssbspace border-spacing CSS properties + * @param float $width width of the containing element * @return array of border spacings * @public * @since 5.9.010 (2010-10-27) @@ -16140,8 +16202,8 @@ class TCPDF { /** * Returns the letter-spacing value from CSS value - * @param $spacing (string) letter-spacing value - * @param $parent (float) font spacing (tracking) value of the parent element + * @param string $spacing letter-spacing value + * @param float $parent font spacing (tracking) value of the parent element * @return float quantity to increases or decreases the space between characters in a text. * @protected * @since 5.9.000 (2010-10-02) @@ -16171,8 +16233,8 @@ class TCPDF { /** * Returns the percentage of font stretching from CSS value - * @param $stretch (string) stretch mode - * @param $parent (float) stretch value of the parent element + * @param string $stretch stretch mode + * @param float $parent stretch value of the parent element * @return float font stretching percentage * @protected * @since 5.9.000 (2010-10-02) @@ -16242,10 +16304,10 @@ class TCPDF { /** * Convert HTML string containing font size value to points - * @param $val (string) String containing font size value and unit. - * @param $refsize (float) Reference font size in points. - * @param $parent_size (float) Parent font size in points. - * @param $defaultunit (string) Default unit (can be one of the following: %, em, ex, px, in, mm, pc, pt). + * @param string $val String containing font size value and unit. + * @param float $refsize Reference font size in points. + * @param float $parent_size Parent font size in points. + * @param string $defaultunit Default unit (can be one of the following: %, em, ex, px, in, mm, pc, pt). * @return float value in points * @public */ @@ -16298,7 +16360,7 @@ class TCPDF { /** * Returns the HTML DOM array. - * @param $html (string) html code + * @param string $html html code * @return array * @protected * @since 3.2.000 (2008-06-20) @@ -16308,15 +16370,15 @@ class TCPDF { $css = array(); // get CSS array defined at previous call $matches = array(); - if (preg_match_all('/([^\<]*)<\/cssarray>/isU', $html, $matches) > 0) { + if (preg_match_all('/([^\<]*?)<\/cssarray>/is', $html, $matches) > 0) { if (isset($matches[1][0])) { $css = array_merge($css, json_decode($this->unhtmlentities($matches[1][0]), true)); } - $html = preg_replace('/(.*?)<\/cssarray>/isU', '', $html); + $html = preg_replace('/(.*?)<\/cssarray>/is', '', $html); } // extract external CSS files $matches = array(); - if (preg_match_all('/]*)>/isU', $html, $matches) > 0) { + if (preg_match_all('/]*?)>/is', $html, $matches) > 0) { foreach ($matches[1] as $key => $link) { $type = array(); if (preg_match('/type[\s]*=[\s]*"text\/css"/', $link, $type)) { @@ -16328,7 +16390,7 @@ class TCPDF { $type = array(); if (preg_match('/href[\s]*=[\s]*"([^"]*)"/', $link, $type) > 0) { // read CSS data file - $cssdata = TCPDF_STATIC::fileGetContents(trim($type[1])); + $cssdata = $this->getCachedFileContents(trim($type[1])); if (($cssdata !== FALSE) AND (strlen($cssdata) > 0)) { $css = array_merge($css, TCPDF_STATIC::extractCSSproperties($cssdata)); } @@ -16339,7 +16401,7 @@ class TCPDF { } // extract style tags $matches = array(); - if (preg_match_all('/]*)>([^\<]*)<\/style>/isU', $html, $matches) > 0) { + if (preg_match_all('/]*?)>([^\<]*?)<\/style>/is', $html, $matches) > 0) { foreach ($matches[1] as $key => $media) { $type = array(); preg_match('/media[\s]*=[\s]*"([^"]*)"/', $media, $type); @@ -16354,8 +16416,8 @@ class TCPDF { // create a special tag to contain the CSS array (used for table content) $csstagarray = ''.htmlentities(json_encode($css)).''; // remove head and style blocks - $html = preg_replace('/]*)>(.*?)<\/head>/siU', '', $html); - $html = preg_replace('/]*)>([^\<]*)<\/style>/isU', '', $html); + $html = preg_replace('/]*?)>(.*?)<\/head>/is', '', $html); + $html = preg_replace('/]*?)>([^\<]*?)<\/style>/is', '', $html); // define block tags $blocktags = array('blockquote','br','dd','dl','div','dt','h1','h2','h3','h4','h5','h6','hr','li','ol','p','pre','ul','tcpdf','table','tr','td'); // define self-closing tags @@ -16549,7 +16611,11 @@ class TCPDF { $dom[($dom[$key]['parent'])]['content'] = str_replace('', '', $dom[($dom[$key]['parent'])]['content']); } // store header rows on a new table - if (($dom[$key]['value'] == 'tr') AND ($dom[($dom[$key]['parent'])]['thead'] === true)) { + if ( + ($dom[$key]['value'] === 'tr') + && !empty($dom[($dom[$key]['parent'])]['thead']) + && ($dom[($dom[$key]['parent'])]['thead'] === true) + ) { if (TCPDF_STATIC::empty_string($dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'])) { $dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'] = $csstagarray.$a[$dom[($dom[($dom[$key]['parent'])]['parent'])]['elkey']]; } @@ -16979,10 +17045,20 @@ class TCPDF { // rows on thead block are printed as a separate table } else { $dom[$key]['thead'] = false; + $parent = $dom[$key]['parent']; + + if (!isset($dom[$parent]['rows'])) { + $dom[$parent]['rows'] = 0; + } // store the number of rows on table element - ++$dom[($dom[$key]['parent'])]['rows']; + ++$dom[$parent]['rows']; + + if (!isset($dom[$parent]['trids'])) { + $dom[$parent]['trids'] = array(); + } + // store the TR elements IDs on table element - array_push($dom[($dom[$key]['parent'])]['trids'], $key); + array_push($dom[$parent]['trids'], $key); } } if (($dom[$key]['value'] == 'th') OR ($dom[$key]['value'] == 'td')) { @@ -17075,6 +17151,7 @@ class TCPDF { } } } + $element = preg_replace("/&NBSP;/i", " ", $element); } $dom[$key]['value'] = stripslashes($this->unhtmlentities($element)); } @@ -17101,7 +17178,7 @@ class TCPDF { /** * Return an hash code used to ensure that the serialized data has been generated by this TCPDF instance. - * @param $data (string) serialized data + * @param string $data serialized data * @return string * @public static */ @@ -17111,7 +17188,7 @@ class TCPDF { /** * Serialize an array of parameters to be used with TCPDF tag in HTML code. - * @param $data (array) parameters array + * @param array $data parameters array * @return string containing serialized data * @public static */ @@ -17122,7 +17199,7 @@ class TCPDF { /** * Unserialize parameters to be used with TCPDF tag in HTML code. - * @param $data (string) serialized data + * @param string $data serialized data * @return array containing unserialized data * @protected static */ @@ -17142,18 +17219,18 @@ class TCPDF { * IMPORTANT: The HTML must be well formatted - try to clean-up it using an application like HTML-Tidy before submitting. * Supported tags are: a, b, blockquote, br, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, img, li, ol, p, pre, small, span, strong, sub, sup, table, tcpdf, td, th, thead, tr, tt, u, ul * NOTE: all the HTML attributes must be enclosed in double-quote. - * @param $w (float) Cell width. If 0, the cell extends up to the right margin. - * @param $h (float) Cell minimum height. The cell extends automatically if needed. - * @param $x (float) upper-left corner X coordinate - * @param $y (float) upper-left corner Y coordinate - * @param $html (string) html text to print. Default value: empty string. - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
                    • 0: no border (default)
                    • 1: frame
                    or a string containing some or all of the following characters (in any order):
                    • L: left
                    • T: top
                    • R: right
                    • B: bottom
                    or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param $ln (int) Indicates where the current position should go after the call. Possible values are:
                    • 0: to the right (or left for RTL language)
                    • 1: to the beginning of the next line
                    • 2: below
                    + * @param float $w Cell width. If 0, the cell extends up to the right margin. + * @param float $h Cell minimum height. The cell extends automatically if needed. + * @param float|null $x upper-left corner X coordinate + * @param float|null $y upper-left corner Y coordinate + * @param string $html html text to print. Default value: empty string. + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
                    • 0: no border (default)
                    • 1: frame
                    or a string containing some or all of the following characters (in any order):
                    • L: left
                    • T: top
                    • R: right
                    • B: bottom
                    or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param int $ln Indicates where the current position should go after the call. Possible values are:
                    • 0: to the right (or left for RTL language)
                    • 1: to the beginning of the next line
                    • 2: below
                    Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. - * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). - * @param $reseth (boolean) if true reset the last cell height (default true). - * @param $align (string) Allows to center or align the text. Possible values are:
                    • L : left align
                    • C : center
                    • R : right align
                    • '' : empty string : left for LTR or right for RTL
                    - * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width. + * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). + * @param boolean $reseth if true reset the last cell height (default true). + * @param string $align Allows to center or align the text. Possible values are:
                    • L : left align
                    • C : center
                    • R : right align
                    • '' : empty string : left for LTR or right for RTL
                    + * @param boolean $autopadding if true, uses internal padding and automatically adjust it to account for line width. * @see Multicell(), writeHTML() * @public */ @@ -17166,12 +17243,12 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * IMPORTANT: The HTML must be well formatted - try to clean-up it using an application like HTML-Tidy before submitting. * Supported tags are: a, b, blockquote, br, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, img, li, ol, p, pre, small, span, strong, sub, sup, table, tcpdf, td, th, thead, tr, tt, u, ul * NOTE: all the HTML attributes must be enclosed in double-quote. - * @param $html (string) text to display - * @param $ln (boolean) if true add a new line after text (default = true) - * @param $fill (boolean) Indicates if the background must be painted (true) or transparent (false). - * @param $reseth (boolean) if true reset the last cell height (default false). - * @param $cell (boolean) if true add the current left (or right for RTL) padding to each Write (default false). - * @param $align (string) Allows to center or align the text. Possible values are:
                    • L : left align
                    • C : center
                    • R : right align
                    • '' : empty string : left for LTR or right for RTL
                    + * @param string $html text to display + * @param boolean $ln if true add a new line after text (default = true) + * @param boolean $fill Indicates if the background must be painted (true) or transparent (false). + * @param boolean $reseth if true reset the last cell height (default false). + * @param boolean $cell if true add the current left (or right for RTL) padding to each Write (default false). + * @param string $align Allows to center or align the text. Possible values are:
                    • L : left align
                    • C : center
                    • R : right align
                    • '' : empty string : left for LTR or right for RTL
                    * @public */ public function writeHTML($html, $ln=true, $fill=false, $reseth=false, $cell=false, $align='') { @@ -17561,7 +17638,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $this->cell_height_ratio = $dom[$key]['line-height']; $fontaligned = true; } - $this->SetFont($fontname, $fontstyle, $fontsize); + $this->setFont($fontname, $fontstyle, $fontsize); // reset row height $this->resetLastH(); $curfontname = $fontname; @@ -17588,16 +17665,16 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: // get current position on page buffer $curpos = $this->pagelen[$startlinepage]; if (isset($dom[$key]['bgcolor']) AND ($dom[$key]['bgcolor'] !== false)) { - $this->SetFillColorArray($dom[$key]['bgcolor']); + $this->setFillColorArray($dom[$key]['bgcolor']); $wfill = true; } else { $wfill = $fill | false; } if (isset($dom[$key]['fgcolor']) AND ($dom[$key]['fgcolor'] !== false)) { - $this->SetTextColorArray($dom[$key]['fgcolor']); + $this->setTextColorArray($dom[$key]['fgcolor']); } if (isset($dom[$key]['strokecolor']) AND ($dom[$key]['strokecolor'] !== false)) { - $this->SetDrawColorArray($dom[$key]['strokecolor']); + $this->setDrawColorArray($dom[$key]['strokecolor']); } if (isset($dom[$key]['align'])) { $lalign = $dom[$key]['align']; @@ -18056,9 +18133,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if (!($dom[$key]['tag'] AND !$dom[$key]['opening'] AND ($dom[$key]['value'] == 'table') AND (isset($this->emptypagemrk[$this->page])) AND ($this->emptypagemrk[$this->page] == $this->pagelen[$this->page]))) { - $this->SetFont($fontname, $fontstyle, $fontsize); + $this->setFont($fontname, $fontstyle, $fontsize); if ($wfill) { - $this->SetFillColorArray($this->bgcolor); + $this->setFillColorArray($this->bgcolor); } } } // end newline @@ -18358,14 +18435,14 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: } elseif (strlen($dom[$key]['value']) > 0) { // print list-item if (!TCPDF_STATIC::empty_string($this->lispacer) AND ($this->lispacer != '^')) { - $this->SetFont($pfontname, $pfontstyle, $pfontsize); + $this->setFont($pfontname, $pfontstyle, $pfontsize); $this->resetLastH(); $minstartliney = $this->y; $maxbottomliney = ($startliney + $this->getCellHeight($this->FontSize)); if (is_numeric($pfontsize) AND ($pfontsize > 0)) { $this->putHtmlListBullet($this->listnum, $this->lispacer, $pfontsize); } - $this->SetFont($curfontname, $curfontstyle, $curfontsize); + $this->setFont($curfontname, $curfontstyle, $curfontsize); $this->resetLastH(); if (is_numeric($pfontsize) AND ($pfontsize > 0) AND is_numeric($curfontsize) AND ($curfontsize > 0) AND ($pfontsize != $curfontsize)) { $pfontascent = $this->getFontAscent($pfontname, $pfontstyle, $pfontsize); @@ -18726,10 +18803,10 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Process opening tags. - * @param $dom (array) html dom array - * @param $key (int) current element id - * @param $cell (boolean) if true add the default left (or right if RTL) padding to each new line (default false). - * @return $dom array + * @param array $dom html dom array + * @param int $key current element id + * @param boolean $cell if true add the default left (or right if RTL) padding to each new line (default false). + * @return array $dom * @protected */ protected function openHTMLTagHandler($dom, $key, $cell) { @@ -18823,7 +18900,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $dom[$key]['old_cell_padding'] = $this->cell_padding; if (isset($tag['attribute']['cellpadding'])) { $pad = $this->getHTMLUnitToUnits($tag['attribute']['cellpadding'], 1, 'px'); - $this->SetCellPadding($pad); + $this->setCellPadding($pad); } elseif (isset($tag['padding'])) { $this->cell_padding = $tag['padding']; } @@ -18864,9 +18941,37 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $hrWidth = $wtmp; } $prevlinewidth = $this->GetLineWidth(); - $this->SetLineWidth($hrHeight); - $this->Line($x, $y, $x + $hrWidth, $y); - $this->SetLineWidth($prevlinewidth); + $this->setLineWidth($hrHeight); + + $lineStyle = array(); + if (isset($tag['fgcolor'])) { + $lineStyle['color'] = $tag['fgcolor']; + } + + if (isset($tag['fgcolor'])) { + $lineStyle['color'] = $tag['fgcolor']; + } + + if (isset($tag['style']['cap'])) { + $lineStyle['cap'] = $tag['style']['cap']; + } + + if (isset($tag['style']['join'])) { + $lineStyle['join'] = $tag['style']['join']; + } + + if (isset($tag['style']['dash'])) { + $lineStyle['dash'] = $tag['style']['dash']; + } + + if (isset($tag['style']['phase'])) { + $lineStyle['phase'] = $tag['style']['phase']; + } + + $lineStyle = array_filter($lineStyle); + + $this->Line($x, $y, $x + $hrWidth, $y, $lineStyle); + $this->setLineWidth($prevlinewidth); $this->addHTMLVertSpace(max($hbc, ($hrHeight / 2)), 0, $cell, !isset($dom[($key + 1)])); break; } @@ -18885,7 +18990,11 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: // data stream $imgsrc = '@'.base64_decode(substr($imgsrc, 1)); $type = ''; - } else { + } elseif ( $this->allowLocalFiles && substr($imgsrc, 0, 7) === 'file://') { + // get image type from a local file path + $imgsrc = substr($imgsrc, 7); + $type = TCPDF_IMAGES::getImageFileType($imgsrc); + } else { if (($imgsrc[0] === '/') AND !empty($_SERVER['DOCUMENT_ROOT']) AND ($_SERVER['DOCUMENT_ROOT'] != '/')) { // fix image path $findroot = strpos($imgsrc, $_SERVER['DOCUMENT_ROOT']); @@ -18957,7 +19066,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $lnky = 0; } $imglink = $this->AddLink(); - $this->SetLink($imglink, $lnky, $page); + $this->setLink($imglink, $lnky, $page); } } } @@ -19111,11 +19220,11 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: break; } case 'sup': { - $this->SetXY($this->GetX(), $this->GetY() - ((0.7 * $this->FontSizePt) / $this->k)); + $this->setXY($this->GetX(), $this->GetY() - ((0.7 * $this->FontSizePt) / $this->k)); break; } case 'sub': { - $this->SetXY($this->GetX(), $this->GetY() + ((0.3 * $this->FontSizePt) / $this->k)); + $this->setXY($this->GetX(), $this->GetY() + ((0.3 * $this->FontSizePt) / $this->k)); break; } case 'h1': @@ -19417,11 +19526,11 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Process closing tags. - * @param $dom (array) html dom array - * @param $key (int) current element id - * @param $cell (boolean) if true add the default left (or right if RTL) padding to each new line (default false). - * @param $maxbottomliney (int) maximum y value of current line - * @return $dom array + * @param array $dom html dom array + * @param int $key current element id + * @param boolean $cell if true add the default left (or right if RTL) padding to each new line (default false). + * @param int $maxbottomliney maximum y value of current line + * @return array $dom * @protected */ protected function closeHTMLTagHandler($dom, $key, $cell, $maxbottomliney=0) { @@ -19626,7 +19735,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $border = $cellpos['border']; } if (isset($cellpos['bgcolor']) AND ($cellpos['bgcolor']) !== false) { - $this->SetFillColorArray($cellpos['bgcolor']); + $this->setFillColorArray($cellpos['bgcolor']); $fill = true; } else { $fill = false; @@ -19807,7 +19916,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: } } if (!$in_table_head) { // we are not inside a thead section - $this->cell_padding = $table_el['old_cell_padding']; + $this->cell_padding = isset($table_el['old_cell_padding']) ? $table_el['old_cell_padding'] : null; // reset row height $this->resetLastH(); if (($this->page == ($this->numpages - 1)) AND ($this->pageopen[$this->numpages])) { @@ -19843,11 +19952,11 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: break; } case 'sup': { - $this->SetXY($this->GetX(), $this->GetY() + ((0.7 * $parent['fontsize']) / $this->k)); + $this->setXY($this->GetX(), $this->GetY() + ((0.7 * $parent['fontsize']) / $this->k)); break; } case 'sub': { - $this->SetXY($this->GetX(), $this->GetY() - ((0.3 * $parent['fontsize']) / $this->k)); + $this->setXY($this->GetX(), $this->GetY() - ((0.3 * $parent['fontsize']) / $this->k)); break; } case 'div': { @@ -19964,11 +20073,11 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Add vertical spaces if needed. - * @param $hbz (string) Distance between current y and line bottom. - * @param $hb (string) The height of the break. - * @param $cell (boolean) if true add the default left (or right if RTL) padding to each new line (default false). - * @param $firsttag (boolean) set to true when the tag is the first. - * @param $lasttag (boolean) set to true when the tag is the last. + * @param string $hbz Distance between current y and line bottom. + * @param string $hb The height of the break. + * @param boolean $cell if true add the default left (or right if RTL) padding to each new line (default false). + * @param boolean $firsttag set to true when the tag is the first. + * @param boolean $lasttag set to true when the tag is the last. * @protected */ protected function addHTMLVertSpace($hbz=0, $hb=0, $cell=false, $firsttag=false, $lasttag=false) { @@ -20008,8 +20117,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Draw an HTML block border and fill - * @param $tag (array) array of tag properties. - * @param $xmax (int) end X coordinate for border. + * @param array $tag array of tag properties. + * @param int $xmax end X coordinate for border. * @protected * @since 5.7.000 (2010-08-03) */ @@ -20035,7 +20144,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if (isset($tag['bgcolor']) AND ($tag['bgcolor'] !== false)) { // get background color $old_bgcolor = $this->bgcolor; - $this->SetFillColorArray($tag['bgcolor']); + $this->setFillColorArray($tag['bgcolor']); $fill = true; } if (!$border AND !$fill) { @@ -20201,7 +20310,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $this->page_regions = $temp_page_regions; if (isset($old_bgcolor)) { // restore background color - $this->SetFillColorArray($old_bgcolor); + $this->setFillColorArray($old_bgcolor); } // restore pointer position $this->x = $prev_x; @@ -20211,7 +20320,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set the default bullet to be used as LI bullet symbol - * @param $symbol (string) character or string to be used (legal values are: '' = automatic, '!' = auto bullet, '#' = auto numbering, 'disc', 'disc', 'circle', 'square', '1', 'decimal', 'decimal-leading-zero', 'i', 'lower-roman', 'I', 'upper-roman', 'a', 'lower-alpha', 'lower-latin', 'A', 'upper-alpha', 'upper-latin', 'lower-greek', 'img|type|width|height|image.ext') + * @param string $symbol character or string to be used (legal values are: '' = automatic, '!' = auto bullet, '#' = auto numbering, 'disc', 'disc', 'circle', 'square', '1', 'decimal', 'decimal-leading-zero', 'i', 'lower-roman', 'I', 'upper-roman', 'a', 'lower-alpha', 'lower-latin', 'A', 'upper-alpha', 'upper-latin', 'lower-greek', 'img|type|width|height|image.ext') * @public * @since 4.0.028 (2008-09-26) */ @@ -20232,13 +20341,13 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set the booklet mode for double-sided pages. - * @param $booklet (boolean) true set the booklet mode on, false otherwise. - * @param $inner (float) Inner page margin. - * @param $outer (float) Outer page margin. + * @param boolean $booklet true set the booklet mode on, false otherwise. + * @param float $inner Inner page margin. + * @param float $outer Outer page margin. * @public * @since 4.2.000 (2008-10-29) */ - public function SetBooklet($booklet=true, $inner=-1, $outer=-1) { + public function setBooklet($booklet=true, $inner=-1, $outer=-1) { $this->booklet = $booklet; if ($inner >= 0) { $this->lMargin = $inner; @@ -20250,7 +20359,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Swap the left and right margins. - * @param $reverse (boolean) if true swap left and right margins. + * @param boolean $reverse if true swap left and right margins. * @protected * @since 4.2.000 (2008-10-29) */ @@ -20274,7 +20383,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * the second level contains 0 for opening tags or 1 for closing tags, * the third level contains the vertical space unit (h) and the number spaces to add (n). * If the h parameter is not specified, default values are used. - * @param $tagvs (array) array of tags and relative vertical spaces. + * @param array $tagvs array of tags and relative vertical spaces. * @public * @since 4.2.001 (2008-10-30) */ @@ -20284,7 +20393,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set custom width for list indentation. - * @param $width (float) width of the indentation. Use negative value to disable it. + * @param float $width width of the indentation. Use negative value to disable it. * @public * @since 4.2.007 (2008-11-12) */ @@ -20294,7 +20403,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set the top/bottom cell sides to be open or closed when the cell cross the page. - * @param $isopen (boolean) if true keeps the top/bottom border open for the cell sides that cross the page. + * @param boolean $isopen if true keeps the top/bottom border open for the cell sides that cross the page. * @public * @since 4.2.010 (2008-11-14) */ @@ -20304,8 +20413,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set the color and font style for HTML links. - * @param $color (array) RGB array of colors - * @param $fontstyle (string) additional font styles to add + * @param array $color RGB array of colors + * @param string $fontstyle additional font styles to add * @public * @since 4.4.003 (2008-12-09) */ @@ -20316,10 +20425,10 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Convert HTML string containing value and unit of measure to user's units or points. - * @param $htmlval (string) String containing values and unit. - * @param $refsize (string) Reference value in points. - * @param $defaultunit (string) Default unit (can be one of the following: %, em, ex, px, in, mm, pc, pt). - * @param $points (boolean) If true returns points, otherwise returns value in user's units. + * @param string $htmlval String containing values and unit. + * @param string $refsize Reference value in points. + * @param string $defaultunit Default unit (can be one of the following: %, em, ex, px, in, mm, pc, pt). + * @param boolean $points If true returns points, otherwise returns value in user's units. * @return float value in user's unit or point if $points=true * @public * @since 4.4.004 (2008-12-10) @@ -20402,9 +20511,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Output an HTML list bullet or ordered item symbol - * @param $listdepth (int) list nesting level - * @param $listtype (string) type of list - * @param $size (float) current font size + * @param int $listdepth list nesting level + * @param string $listtype type of list + * @param float $size current font size * @protected * @since 4.4.004 (2008-12-10) */ @@ -20599,9 +20708,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $this->x = $tmpx; $this->lispacer = '^'; // restore colors - $this->SetFillColorArray($bgcolor); - $this->SetDrawColorArray($strokecolor); - $this->SettextColorArray($color); + $this->setFillColorArray($bgcolor); + $this->setDrawColorArray($strokecolor); + $this->settextColorArray($color); } /** @@ -20666,8 +20775,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set graphic variables. - * @param $gvars (array) array of graphic variablesto restore - * @param $extended (boolean) if true restore extended graphic variables + * @param array $gvars array of graphic variablesto restore + * @param boolean $extended if true restore extended graphic variables * @protected * @since 4.2.010 (2008-11-14) */ @@ -20727,7 +20836,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: } $this->_out(''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor.''); if (!TCPDF_STATIC::empty_string($this->FontFamily)) { - $this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt); + $this->setFont($this->FontFamily, $this->FontStyle, $this->FontSizePt); } } @@ -20749,7 +20858,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set buffer content (always append data). - * @param $data (string) data + * @param string $data data * @protected * @since 4.5.000 (2009-01-02) */ @@ -20760,7 +20869,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Replace the buffer content - * @param $data (string) data + * @param string $data data * @protected * @since 5.5.000 (2010-06-22) */ @@ -20781,9 +20890,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set page buffer content. - * @param $page (int) page number - * @param $data (string) page data - * @param $append (boolean) if true append data, false replace. + * @param int $page page number + * @param string $data page data + * @param boolean $append if true append data, false replace. * @protected * @since 4.5.000 (2008-12-31) */ @@ -20802,7 +20911,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Get page buffer content. - * @param $page (int) page number + * @param int $page page number * @return string page buffer content or false in case of error * @protected * @since 4.5.000 (2008-12-31) @@ -20816,8 +20925,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set image buffer content. - * @param $image (string) image key - * @param $data (array) image data + * @param string $image image key + * @param array $data image data * @return int image index number * @protected * @since 4.5.000 (2008-12-31) @@ -20834,9 +20943,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set image buffer content for a specified sub-key. - * @param $image (string) image key - * @param $key (string) image sub-key - * @param $data (array) image data + * @param string $image image key + * @param string $key image sub-key + * @param array $data image data * @protected * @since 4.5.000 (2008-12-31) */ @@ -20849,8 +20958,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Get image buffer content. - * @param $image (string) image key - * @return string image buffer content or false in case of error + * @param string $image image key + * @return string|false image buffer content or false in case of error * @protected * @since 4.5.000 (2008-12-31) */ @@ -20863,8 +20972,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set font buffer content. - * @param $font (string) font key - * @param $data (array) font data + * @param string $font font key + * @param array $data font data * @protected * @since 4.5.000 (2009-01-02) */ @@ -20881,9 +20990,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set font buffer content. - * @param $font (string) font key - * @param $key (string) font sub-key - * @param $data (array) font data + * @param string $font font key + * @param string $key font sub-key + * @param mixed $data font data * @protected * @since 4.5.000 (2009-01-02) */ @@ -20896,8 +21005,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Get font buffer content. - * @param $font (string) font key - * @return string font buffer content or false in case of error + * @param string $font font key + * @return string|false font buffer content or false in case of error * @protected * @since 4.5.000 (2009-01-02) */ @@ -20910,9 +21019,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Move a page to a previous position. - * @param $frompage (int) number of the source page - * @param $topage (int) number of the destination page (must be less than $frompage) - * @return true in case of success, false in case of error. + * @param int $frompage number of the source page + * @param int $topage number of the destination page (must be less than $frompage) + * @return bool true in case of success, false in case of error. * @public * @since 4.5.000 (2009-01-02) */ @@ -21082,8 +21191,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Remove the specified page. - * @param $page (int) page to remove - * @return true in case of success, false in case of error. + * @param int $page page to remove + * @return bool true in case of success, false in case of error. * @public * @since 4.6.004 (2009-04-23) */ @@ -21272,8 +21381,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Clone the specified page to a new page. - * @param $page (int) number of page to copy (0 = current page) - * @return true in case of success, false in case of error. + * @param int $page number of page to copy (0 = current page) + * @return bool true in case of success, false in case of error. * @public * @since 4.9.015 (2010-04-20) */ @@ -21343,18 +21452,18 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * Before calling this method you have to open the page using the addTOCPage() method. * After calling this method you have to call endTOCPage() to close the TOC page. * You can override this method to achieve different styles. - * @param $page (int) page number where this TOC should be inserted (leave empty for current page). - * @param $numbersfont (string) set the font for page numbers (please use monospaced font for better alignment). - * @param $filler (string) string used to fill the space between text and page number. - * @param $toc_name (string) name to use for TOC bookmark. - * @param $style (string) Font style for title: B = Bold, I = Italic, BI = Bold + Italic. - * @param $color (array) RGB color array for bookmark title (values from 0 to 255). + * @param int|null $page page number where this TOC should be inserted (leave empty for current page). + * @param string $numbersfont set the font for page numbers (please use monospaced font for better alignment). + * @param string $filler string used to fill the space between text and page number. + * @param string $toc_name name to use for TOC bookmark. + * @param string $style Font style for title: B = Bold, I = Italic, BI = Bold + Italic. + * @param array $color RGB color array for bookmark title (values from 0 to 255). * @public * @author Nicola Asuni * @since 4.5.000 (2009-01-02) * @see addTOCPage(), endTOCPage(), addHTMLTOC() */ - public function addTOC($page='', $numbersfont='', $filler='.', $toc_name='TOC', $style='', $color=array(0,0,0)) { + public function addTOC($page=null, $numbersfont='', $filler='.', $toc_name='TOC', $style='', $color=array(0,0,0)) { $fontsize = $this->FontSizePt; $fontfamily = $this->FontFamily; $fontstyle = $this->FontStyle; @@ -21382,7 +21491,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $page = 1; } } - $this->SetFont($numbersfont, $fontstyle, $fontsize); + $this->setFont($numbersfont, $fontstyle, $fontsize); $numwidth = $this->GetStringWidth('00000'); $maxpage = 0; //used for pages on attached documents foreach ($this->outlines as $key => $outline) { @@ -21398,11 +21507,11 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $alignnum = 'R'; } if ($outline['l'] == 0) { - $this->SetFont($fontfamily, $outline['s'].'B', $fontsize); + $this->setFont($fontfamily, $outline['s'].'B', $fontsize); } else { - $this->SetFont($fontfamily, $outline['s'], $fontsize - $outline['l']); + $this->setFont($fontfamily, $outline['s'], $fontsize - $outline['l']); } - $this->SetTextColorArray($outline['c']); + $this->setTextColorArray($outline['c']); // check for page break $this->checkPageBreak(2 * $this->getCellHeight($this->FontSize)); // set margins and X position @@ -21422,7 +21531,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $current_page = $this->page; $current_column = $this->current_column; } - $this->SetX($x_start); + $this->setX($x_start); $indent = ($spacer * $outline['l']); if ($this->rtl) { $this->x -= $indent; @@ -21432,7 +21541,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $this->lMargin = $this->x; } $link = $this->AddLink(); - $this->SetLink($link, $outline['y'], $outline['p']); + $this->setLink($link, $outline['y'], $outline['p']); // write the text if ($this->rtl) { $txt = ' '.$outline['t']; @@ -21445,7 +21554,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: } else { $tw = $this->w - $this->rMargin - $this->x; } - $this->SetFont($numbersfont, $fontstyle, $fontsize); + $this->setFont($numbersfont, $fontstyle, $fontsize); if (TCPDF_STATIC::empty_string($page)) { $pagenum = $outline['p']; } else { @@ -21553,18 +21662,18 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * This method must be called after all Bookmarks were set. * Before calling this method you have to open the page using the addTOCPage() method. * After calling this method you have to call endTOCPage() to close the TOC page. - * @param $page (int) page number where this TOC should be inserted (leave empty for current page). - * @param $toc_name (string) name to use for TOC bookmark. - * @param $templates (array) array of html templates. Use: "#TOC_DESCRIPTION#" for bookmark title, "#TOC_PAGE_NUMBER#" for page number. - * @param $correct_align (boolean) if true correct the number alignment (numbers must be in monospaced font like courier and right aligned on LTR, or left aligned on RTL) - * @param $style (string) Font style for title: B = Bold, I = Italic, BI = Bold + Italic. - * @param $color (array) RGB color array for title (values from 0 to 255). + * @param int|null $page page number where this TOC should be inserted (leave empty for current page). + * @param string $toc_name name to use for TOC bookmark. + * @param array $templates array of html templates. Use: "#TOC_DESCRIPTION#" for bookmark title, "#TOC_PAGE_NUMBER#" for page number. + * @param boolean $correct_align if true correct the number alignment (numbers must be in monospaced font like courier and right aligned on LTR, or left aligned on RTL) + * @param string $style Font style for title: B = Bold, I = Italic, BI = Bold + Italic. + * @param array $color RGB color array for title (values from 0 to 255). * @public * @author Nicola Asuni * @since 5.0.001 (2010-05-06) * @see addTOCPage(), endTOCPage(), addTOC() */ - public function addHTMLTOC($page='', $toc_name='TOC', $templates=array(), $correct_align=true, $style='', $color=array(0,0,0)) { + public function addHTMLTOC($page=null, $toc_name='TOC', $templates=array(), $correct_align=true, $style='', $color=array(0,0,0)) { $filler = ' '; $prev_htmlLinkColorArray = $this->htmlLinkColorArray; $prev_htmlLinkFontStyle = $this->htmlLinkFontStyle; @@ -21580,12 +21689,12 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $dom = $this->getHtmlDomArray($html); foreach ($dom as $key => $value) { if ($value['value'] == '#TOC_PAGE_NUMBER#') { - $this->SetFont($dom[($key - 1)]['fontname']); + $this->setFont($dom[($key - 1)]['fontname']); $templates['F'.$level] = $this->isUnicodeFont(); } } } - $this->SetFont($current_font); + $this->setFont($current_font); $maxpage = 0; //used for pages on attached documents foreach ($this->outlines as $key => $outline) { // get HTML template @@ -21717,27 +21826,37 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: public function commitTransaction() { if (isset($this->objcopy)) { $this->objcopy->_destroy(true, true); + /* The unique file_id should not be used during cleanup again */ + $this->objcopy->file_id = NULL; unset($this->objcopy); } } /** * This method allows to undo the latest transaction by returning the latest saved TCPDF object with startTransaction(). - * @param $self (boolean) if true restores current class object to previous state without the need of reassignment via the returned value. + * @param boolean $self if true restores current class object to previous state without the need of reassignment via the returned value. * @return TCPDF object. * @public * @since 4.5.029 (2009-03-19) */ public function rollbackTransaction($self=false) { if (isset($this->objcopy)) { + $objcopy = $this->objcopy; $this->_destroy(true, true); if ($self) { - $objvars = get_object_vars($this->objcopy); + $objvars = get_object_vars($objcopy); foreach ($objvars as $key => $value) { $this->$key = $value; } + $objcopy->_destroy(true, true); + /* The unique file_id should not be used during cleanup again */ + $objcopy->file_id = NULL; + unset($objcopy); + return $this; } - return $this->objcopy; + /* The unique file_id should not be used during cleanup again */ + $this->file_id = NULL; + return $objcopy; } return $this; } @@ -21746,13 +21865,13 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set multiple columns of the same size - * @param $numcols (int) number of columns (set to zero to disable columns mode) - * @param $width (int) column width - * @param $y (int) column starting Y position (leave empty for current Y position) + * @param int $numcols number of columns (set to zero to disable columns mode) + * @param int $width column width + * @param int|null $y column starting Y position (leave empty for current Y position) * @public * @since 4.9.001 (2010-03-28) */ - public function setEqualColumns($numcols=0, $width=0, $y='') { + public function setEqualColumns($numcols=0, $width=0, $y=null) { $this->columns = array(); if ($numcols < 2) { $numcols = 0; @@ -21793,7 +21912,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set columns array. * Each column is represented by an array of arrays with the following keys: (w = width, s = space between columns, y = column top position). - * @param $columns (array) + * @param array $columns * @public * @since 4.9.001 (2010-03-28) */ @@ -21807,12 +21926,12 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set position at a given column - * @param $col (int) column number (from 0 to getNumberOfColumns()-1); empty string = current column. + * @param int|null $col column number (from 0 to getNumberOfColumns()-1); empty string = current column. * @public * @since 4.9.001 (2010-03-28) */ - public function selectColumn($col='') { - if (is_string($col)) { + public function selectColumn($col=null) { + if (TCPDF_STATIC::empty_string($col)) { $col = $this->current_column; } elseif ($col >= $this->num_columns) { $col = 0; @@ -21906,9 +22025,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set Text rendering mode. - * @param $stroke (int) outline size in user units (0 = disable). - * @param $fill (boolean) if true fills the text (default). - * @param $clip (boolean) if true activate clipping mode + * @param int $stroke outline size in user units (0 = disable). + * @param boolean $fill if true fills the text (default). + * @param boolean $clip if true activate clipping mode * @public * @since 4.9.008 (2009-04-02) */ @@ -21963,7 +22082,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set parameters for drop shadow effect for text. - * @param $params (array) Array of parameters: enabled (boolean) set to true to enable shadow; depth_w (float) shadow width in user units; depth_h (float) shadow height in user units; color (array) shadow color or false to use the stroke color; opacity (float) Alpha value: real value from 0 (transparent) to 1 (opaque); blend_mode (string) blend mode, one of the following: Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity. + * @param array $params Array of parameters: enabled (boolean) set to true to enable shadow; depth_w (float) shadow width in user units; depth_h (float) shadow height in user units; color (array) shadow color or false to use the stroke color; opacity (float) Alpha value: real value from 0 (transparent) to 1 (opaque); blend_mode (string) blend mode, one of the following: Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity. * @since 5.9.174 (2012-07-25) * @public */ @@ -22005,7 +22124,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Return the text shadow parameters array. - * @return Array of parameters. + * @return array array of parameters. * @since 5.9.174 (2012-07-25) * @public */ @@ -22015,13 +22134,13 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Returns an array of chars containing soft hyphens. - * @param $word (array) array of chars - * @param $patterns (array) Array of hypenation patterns. - * @param $dictionary (array) Array of words to be returned without applying the hyphenation algorithm. - * @param $leftmin (int) Minimum number of character to leave on the left of the word without applying the hyphens. - * @param $rightmin (int) Minimum number of character to leave on the right of the word without applying the hyphens. - * @param $charmin (int) Minimum word length to apply the hyphenation algorithm. - * @param $charmax (int) Maximum length of broken piece of word. + * @param array $word array of chars + * @param array $patterns Array of hypenation patterns. + * @param array $dictionary Array of words to be returned without applying the hyphenation algorithm. + * @param int $leftmin Minimum number of character to leave on the left of the word without applying the hyphens. + * @param int $rightmin Minimum number of character to leave on the right of the word without applying the hyphens. + * @param int $charmin Minimum word length to apply the hyphenation algorithm. + * @param int $charmax Maximum length of broken piece of word. * @return array text with soft hyphens * @author Nicola Asuni * @since 4.9.012 (2010-04-12) @@ -22095,14 +22214,14 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Returns text with soft hyphens. - * @param $text (string) text to process - * @param $patterns (mixed) Array of hypenation patterns or a TEX file containing hypenation patterns. TEX patterns can be downloaded from http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ - * @param $dictionary (array) Array of words to be returned without applying the hyphenation algorithm. - * @param $leftmin (int) Minimum number of character to leave on the left of the word without applying the hyphens. - * @param $rightmin (int) Minimum number of character to leave on the right of the word without applying the hyphens. - * @param $charmin (int) Minimum word length to apply the hyphenation algorithm. - * @param $charmax (int) Maximum length of broken piece of word. - * @return array text with soft hyphens + * @param string $text text to process + * @param mixed $patterns Array of hypenation patterns or a TEX file containing hypenation patterns. TEX patterns can be downloaded from http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ + * @param array $dictionary Array of words to be returned without applying the hyphenation algorithm. + * @param int $leftmin Minimum number of character to leave on the left of the word without applying the hyphens. + * @param int $rightmin Minimum number of character to leave on the right of the word without applying the hyphens. + * @param int $charmin Minimum word length to apply the hyphenation algorithm. + * @param int $charmax Maximum length of broken piece of word. + * @return string text with soft hyphens * @author Nicola Asuni * @since 4.9.012 (2010-04-12) * @public @@ -22167,7 +22286,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Enable/disable rasterization of vector images using ImageMagick library. - * @param $mode (boolean) if true enable rasterization, false otherwise. + * @param boolean $mode if true enable rasterization, false otherwise. * @public * @since 5.0.000 (2010-04-27) */ @@ -22177,7 +22296,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Enable or disable default option for font subsetting. - * @param $enable (boolean) if true enable font subsetting by default. + * @param boolean $enable if true enable font subsetting by default. * @author Nicola Asuni * @public * @since 5.3.002 (2010-06-07) @@ -22192,7 +22311,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Return the default option for font subsetting. - * @return boolean default font subsetting state. + * @return bool default font subsetting state. * @author Nicola Asuni * @public * @since 5.3.002 (2010-06-07) @@ -22203,9 +22322,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Left trim the input string - * @param $str (string) string to trim - * @param $replace (string) string that replace spaces. - * @return left trimmed string + * @param string $str string to trim + * @param string $replace string that replace spaces. + * @return string left trimmed string * @author Nicola Asuni * @public * @since 5.8.000 (2010-08-11) @@ -22216,9 +22335,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Right trim the input string - * @param $str (string) string to trim - * @param $replace (string) string that replace spaces. - * @return right trimmed string + * @param string $str string to trim + * @param string $replace string that replace spaces. + * @return string right trimmed string * @author Nicola Asuni * @public * @since 5.8.000 (2010-08-11) @@ -22229,9 +22348,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Trim the input string - * @param $str (string) string to trim - * @param $replace (string) string that replace spaces. - * @return trimmed string + * @param string $str string to trim + * @param string $replace string that replace spaces. + * @return string trimmed string * @author Nicola Asuni * @public * @since 5.8.000 (2010-08-11) @@ -22244,7 +22363,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Return true if the current font is unicode type. - * @return true for unicode font, false otherwise. + * @return bool true for unicode font, false otherwise. * @author Nicola Asuni * @public * @since 5.8.002 (2010-08-14) @@ -22255,7 +22374,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Return normalized font name - * @param $fontfamily (string) property string containing font family names + * @param string $fontfamily property string containing font family names * @return string normalized font name * @author Nicola Asuni * @public @@ -22296,10 +22415,10 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * An XObject Template is a PDF block that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). * An XObject Template may be painted multiple times, either on several pages or at several locations on the same page and produces the same results each time, subject only to the graphics state at the time it is invoked. * Note: X,Y coordinates will be reset to 0,0. - * @param $w (int) Template width in user units (empty string or zero = page width less margins). - * @param $h (int) Template height in user units (empty string or zero = page height less margins). - * @param $group (mixed) Set transparency group. Can be a boolean value or an array specifying optional parameters: 'CS' (solour space name), 'I' (boolean flag to indicate isolated group) and 'K' (boolean flag to indicate knockout group). - * @return int the XObject Template ID in case of success or false in case of error. + * @param int $w Template width in user units (empty string or zero = page width less margins). + * @param int $h Template height in user units (empty string or zero = page height less margins). + * @param mixed $group Set transparency group. Can be a boolean value or an array specifying optional parameters: 'CS' (solour space name), 'I' (boolean flag to indicate isolated group) and 'K' (boolean flag to indicate knockout group). + * @return string|false the XObject Template ID in case of success or false in case of error. * @author Nicola Asuni * @public * @since 5.8.017 (2010-08-24) @@ -22332,7 +22451,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: // set new environment $this->num_columns = 1; $this->current_column = 0; - $this->SetAutoPageBreak(false); + $this->setAutoPageBreak(false); if (($w === '') OR ($w <= 0)) { $w = $this->w - $this->lMargin - $this->rMargin; } @@ -22364,7 +22483,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * End the current XObject Template started with startTemplate() and restore the previous graphic state. * An XObject Template is a PDF block that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). * An XObject Template may be painted multiple times, either on several pages or at several locations on the same page and produces the same results each time, subject only to the graphics state at the time it is invoked. - * @return int the XObject Template ID in case of success or false in case of error. + * @return string|false the XObject Template ID in case of success or false in case of error. * @author Nicola Asuni * @public * @since 5.8.017 (2010-08-24) @@ -22386,20 +22505,20 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * You can print an XObject Template inside the currently opened Template. * An XObject Template is a PDF block that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). * An XObject Template may be painted multiple times, either on several pages or at several locations on the same page and produces the same results each time, subject only to the graphics state at the time it is invoked. - * @param $id (string) The ID of XObject Template to print. - * @param $x (int) X position in user units (empty string = current x position) - * @param $y (int) Y position in user units (empty string = current y position) - * @param $w (int) Width in user units (zero = remaining page width) - * @param $h (int) Height in user units (zero = remaining page height) - * @param $align (string) Indicates the alignment of the pointer next to template insertion relative to template height. The value can be:
                    • T: top-right for LTR or top-left for RTL
                    • M: middle-right for LTR or middle-left for RTL
                    • B: bottom-right for LTR or bottom-left for RTL
                    • N: next line
                    - * @param $palign (string) Allows to center or align the template on the current line. Possible values are:
                    • L : left align
                    • C : center
                    • R : right align
                    • '' : empty string : left for LTR or right for RTL
                    - * @param $fitonpage (boolean) If true the template is resized to not exceed page dimensions. + * @param string $id The ID of XObject Template to print. + * @param float|null $x X position in user units (empty string = current x position) + * @param float|null $y Y position in user units (empty string = current y position) + * @param float $w Width in user units (zero = remaining page width) + * @param float $h Height in user units (zero = remaining page height) + * @param string $align Indicates the alignment of the pointer next to template insertion relative to template height. The value can be:
                    • T: top-right for LTR or top-left for RTL
                    • M: middle-right for LTR or middle-left for RTL
                    • B: bottom-right for LTR or bottom-left for RTL
                    • N: next line
                    + * @param string $palign Allows to center or align the template on the current line. Possible values are:
                    • L : left align
                    • C : center
                    • R : right align
                    • '' : empty string : left for LTR or right for RTL
                    + * @param boolean $fitonpage If true the template is resized to not exceed page dimensions. * @author Nicola Asuni * @public * @since 5.8.017 (2010-08-24) * @see startTemplate(), endTemplate() */ - public function printTemplate($id, $x='', $y='', $w=0, $h=0, $align='', $palign='', $fitonpage=false) { + public function printTemplate($id, $x=null, $y=null, $w=0, $h=0, $align='', $palign='', $fitonpage=false) { if ($this->state != 2) { return; } @@ -22416,10 +22535,10 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: } } // set default values - if ($x === '') { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -22516,7 +22635,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: break; } case 'N': { - $this->SetY($rb_y); + $this->setY($rb_y); break; } default:{ @@ -22527,7 +22646,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set the percentage of character stretching. - * @param $perc (int) percentage of stretching (100 = no stretching) + * @param int $perc percentage of stretching (100 = no stretching) * @author Nicola Asuni * @public * @since 5.9.000 (2010-09-29) @@ -22549,7 +22668,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Set the amount to increase or decrease the space between characters in a text. - * @param $spacing (float) amount to increase or decrease the space between characters in a text (0 = default spacing) + * @param float $spacing amount to increase or decrease the space between characters in a text (0 = default spacing) * @author Nicola Asuni * @public * @since 5.9.000 (2010-09-29) @@ -22586,7 +22705,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * A no-write region is a portion of the page with a rectangular or trapezium shape that will not be covered when writing text or html code. * A region is always aligned on the left or right side of the page ad is defined using a vertical segment. * You can set multiple regions for the same page. - * @param $regions (array) array of no-write regions. For each region you can define an array as follow: ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right). Omit this parameter to remove all regions. + * @param array $regions array of no-write regions. For each region you can define an array as follow: ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right). Omit this parameter to remove all regions. * @author Nicola Asuni * @public * @since 5.9.003 (2010-10-13) @@ -22606,7 +22725,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * A no-write region is a portion of the page with a rectangular or trapezium shape that will not be covered when writing text or html code. * A region is always aligned on the left or right side of the page ad is defined using a vertical segment. * You can set multiple regions for the same page. - * @param $region (array) array of a single no-write region array: ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right). + * @param array $region array of a single no-write region array: ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right). * @author Nicola Asuni * @public * @since 5.9.003 (2010-10-13) @@ -22625,7 +22744,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Remove a single no-write region. - * @param $key (int) region key + * @param int $key region key * @author Nicola Asuni * @public * @since 5.9.003 (2010-10-13) @@ -22641,10 +22760,10 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: * Check page for no-write regions and adapt current coordinates and page margins if necessary. * A no-write region is a portion of the page with a rectangular or trapezium shape that will not be covered when writing text or html code. * A region is always aligned on the left or right side of the page ad is defined using a vertical segment. - * @param $h (float) height of the text/image/object to print in user units - * @param $x (float) current X coordinate in user units - * @param $y (float) current Y coordinate in user units - * @return array($x, $y) + * @param float $h height of the text/image/object to print in user units + * @param float $x current X coordinate in user units + * @param float $y current Y coordinate in user units + * @return float[] array($x, $y) * @author Nicola Asuni * @protected * @since 5.9.003 (2010-10-13) @@ -22738,21 +22857,21 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Embedd a Scalable Vector Graphics (SVG) image. * NOTE: SVG standard is not yet fully implemented, use the setRasterizeVectorImages() method to enable/disable rasterization of vector images using ImageMagick library. - * @param $file (string) Name of the SVG file or a '@' character followed by the SVG data string. - * @param $x (float) Abscissa of the upper-left corner. - * @param $y (float) Ordinate of the upper-left corner. - * @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param $link (mixed) URL or identifier returned by AddLink(). - * @param $align (string) Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
                    • T: top-right for LTR or top-left for RTL
                    • M: middle-right for LTR or middle-left for RTL
                    • B: bottom-right for LTR or bottom-left for RTL
                    • N: next line
                    If the alignment is an empty string, then the pointer will be restored on the starting SVG position. - * @param $palign (string) Allows to center or align the image on the current line. Possible values are:
                    • L : left align
                    • C : center
                    • R : right align
                    • '' : empty string : left for LTR or right for RTL
                    - * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
                    • 0: no border (default)
                    • 1: frame
                    or a string containing some or all of the following characters (in any order):
                    • L: left
                    • T: top
                    • R: right
                    • B: bottom
                    or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param $fitonpage (boolean) if true the image is resized to not exceed page dimensions. + * @param string $file Name of the SVG file or a '@' character followed by the SVG data string. + * @param float|null $x Abscissa of the upper-left corner. + * @param float|null $y Ordinate of the upper-left corner. + * @param float $w Width of the image in the page. If not specified or equal to zero, it is automatically calculated. + * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated. + * @param mixed $link URL or identifier returned by AddLink(). + * @param string $align Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
                    • T: top-right for LTR or top-left for RTL
                    • M: middle-right for LTR or middle-left for RTL
                    • B: bottom-right for LTR or bottom-left for RTL
                    • N: next line
                    If the alignment is an empty string, then the pointer will be restored on the starting SVG position. + * @param string $palign Allows to center or align the image on the current line. Possible values are:
                    • L : left align
                    • C : center
                    • R : right align
                    • '' : empty string : left for LTR or right for RTL
                    + * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:
                    • 0: no border (default)
                    • 1: frame
                    or a string containing some or all of the following characters (in any order):
                    • L: left
                    • T: top
                    • R: right
                    • B: bottom
                    or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + * @param boolean $fitonpage if true the image is resized to not exceed page dimensions. * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @public */ - public function ImageSVG($file, $x='', $y='', $w=0, $h=0, $link='', $align='', $palign='', $border=0, $fitonpage=false) { + public function ImageSVG($file, $x=null, $y=null, $w=0, $h=0, $link='', $align='', $palign='', $border=0, $fitonpage=false) { if ($this->state != 2) { return; } @@ -22776,15 +22895,15 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $svgdata = substr($file, 1); } else { // SVG file $this->svgdir = dirname($file); - $svgdata = TCPDF_STATIC::fileGetContents($file); + $svgdata = $this->getCachedFileContents($file); } if ($svgdata === FALSE) { $this->Error('SVG file not found: '.$file); } - if ($x === '') { + if (TCPDF_STATIC::empty_string($x)) { $x = $this->x; } - if ($y === '') { + if (TCPDF_STATIC::empty_string($y)) { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary @@ -22975,8 +23094,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $page_break_mode = $this->AutoPageBreak; $page_break_margin = $this->getBreakMargin(); $cell_padding = $this->cell_padding; - $this->SetCellPadding(0); - $this->SetAutoPageBreak(false); + $this->setCellPadding(0); + $this->setAutoPageBreak(false); // save the current graphic state $this->_out('q'.$this->epsmarker); // set initial clipping mask @@ -22986,22 +23105,26 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $f = ($this->h - $oy) * $this->k * (1 - $svgscale_y); $this->_out(sprintf('%F %F %F %F %F %F cm', $svgscale_x, 0, 0, $svgscale_y, ($e + $svgoffset_x), ($f + $svgoffset_y))); // creates a new XML parser to be used by the other XML functions - $this->parser = xml_parser_create('UTF-8'); + $parser = xml_parser_create('UTF-8'); // the following function allows to use parser inside object - xml_set_object($this->parser, $this); + xml_set_object($parser, $this); // disable case-folding for this XML parser - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); // sets the element handler functions for the XML parser - xml_set_element_handler($this->parser, 'startSVGElementHandler', 'endSVGElementHandler'); + xml_set_element_handler($parser, 'startSVGElementHandler', 'endSVGElementHandler'); // sets the character data handler function for the XML parser - xml_set_character_data_handler($this->parser, 'segSVGContentHandler'); + xml_set_character_data_handler($parser, 'segSVGContentHandler'); // start parsing an XML document - if (!xml_parse($this->parser, $svgdata)) { - $error_message = sprintf('SVG Error: %s at line %d', xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser)); + if (!xml_parse($parser, $svgdata)) { + $error_message = sprintf('SVG Error: %s at line %d', xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser)); $this->Error($error_message); } // free this XML parser - xml_parser_free($this->parser); + xml_parser_free($parser); + + // >= PHP 7.0.0 "explicitly unset the reference to parser to avoid memory leaks" + unset($parser); + // restore previous graphic state $this->_out($this->epsmarker.'Q'); // restore graphic vars @@ -23040,7 +23163,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: break; } case 'N':{ - $this->SetY($this->img_rb_y); + $this->setY($this->img_rb_y); break; } default:{ @@ -23062,13 +23185,13 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: } $this->endlinex = $this->img_rb_x; // restore page break - $this->SetAutoPageBreak($page_break_mode, $page_break_margin); + $this->setAutoPageBreak($page_break_mode, $page_break_margin); $this->cell_padding = $cell_padding; } /** * Convert SVG transformation matrix to PDF. - * @param $tm (array) original SVG transformation matrix + * @param array $tm original SVG transformation matrix * @return array transformation matrix * @protected * @since 5.0.000 (2010-05-02) @@ -23089,7 +23212,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Apply SVG graphic transformation matrix. - * @param $tm (array) original SVG transformation matrix + * @param array $tm original SVG transformation matrix * @protected * @since 5.0.000 (2010-05-02) */ @@ -23099,15 +23222,15 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Apply the requested SVG styles (*** TO BE COMPLETED ***) - * @param $svgstyle (array) array of SVG styles to apply - * @param $prevsvgstyle (array) array of previous SVG style - * @param $x (int) X origin of the bounding box - * @param $y (int) Y origin of the bounding box - * @param $w (int) width of the bounding box - * @param $h (int) height of the bounding box - * @param $clip_function (string) clip function - * @param $clip_params (array) array of parameters for clipping function - * @return object style + * @param array $svgstyle array of SVG styles to apply + * @param array $prevsvgstyle array of previous SVG style + * @param int $x X origin of the bounding box + * @param int $y Y origin of the bounding box + * @param int $w width of the bounding box + * @param int $h height of the bounding box + * @param string $clip_function clip function + * @param array $clip_params array of parameters for clipping function + * @return string style * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected @@ -23135,10 +23258,10 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: } // color $fill_color = TCPDF_COLORS::convertHTMLColorToDec($svgstyle['color'], $this->spot_colors); - $this->SetFillColorArray($fill_color); + $this->setFillColorArray($fill_color); // text color $text_color = TCPDF_COLORS::convertHTMLColorToDec($svgstyle['text-color'], $this->spot_colors); - $this->SetTextColorArray($text_color); + $this->setTextColorArray($text_color); // clip if (preg_match('/rect\(([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)\)/si', $svgstyle['clip'], $regs)) { $top = (isset($regs[1])?$this->getHTMLUnitToUnits($regs[1], 0, $this->svgunit, false):0); @@ -23265,7 +23388,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if ($svgstyle['fill-opacity'] != 1) { $this->setAlpha($this->alpha['CA'], 'Normal', $svgstyle['fill-opacity'], false); } - $this->SetFillColorArray($fill_color); + $this->setFillColorArray($fill_color); if ($svgstyle['fill-rule'] == 'evenodd') { $objstyle .= 'F*'; } else { @@ -23288,7 +23411,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if (isset($svgstyle['stroke-dasharray']) AND !empty($svgstyle['stroke-dasharray']) AND ($svgstyle['stroke-dasharray'] != 'none')) { $stroke_style['dash'] = $svgstyle['stroke-dasharray']; } - $this->SetLineStyle($stroke_style); + $this->setLineStyle($stroke_style); $objstyle .= 'D'; } // font @@ -23383,7 +23506,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: break; } } - $this->SetFont($font_family, $font_style, $font_size); + $this->setFont($font_family, $font_style, $font_size); $this->setFontStretching($font_stretch); $this->setFontSpacing($font_spacing); return $objstyle; @@ -23391,8 +23514,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Draws an SVG path - * @param $d (string) attribute d of the path SVG element - * @param $style (string) Style of rendering. Possible values are: + * @param string $d attribute d of the path SVG element + * @param string $style Style of rendering. Possible values are: *
                      *
                    • D or empty string: Draw (default).
                    • *
                    • F: Fill.
                    • @@ -23418,6 +23541,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: } $paths = array(); $d = preg_replace('/([0-9ACHLMQSTVZ])([\-\+])/si', '\\1 \\2', $d); + $d = preg_replace('/(\.[0-9]+)(\.)/s', '\\1 \\2', $d); preg_match_all('/([ACHLMQSTVZ])[\s]*([^ACHLMQSTVZ\"]*)/si', $d, $paths, PREG_SET_ORDER); $x = 0; $y = 0; @@ -23767,7 +23891,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Return the tag name without the namespace - * @param $name (string) Tag name + * @param string $name Tag name * @protected */ protected function removeTagNamespace($name) { @@ -23780,10 +23904,10 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Sets the opening SVG element handler function for the XML parser. (*** TO BE COMPLETED ***) - * @param $parser (resource) The first parameter, parser, is a reference to the XML parser calling the handler. - * @param $name (string) The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. - * @param $attribs (array) The third parameter, attribs, contains an associative array with the element's attributes (if any). The keys of this array are the attribute names, the values are the attribute values. Attribute names are case-folded on the same criteria as element names. Attribute values are not case-folded. The original order of the attributes can be retrieved by walking through attribs the normal way, using each(). The first key in the array was the first attribute, and so on. - * @param $ctm (array) tranformation matrix for clipping mode (starting transformation matrix). + * @param resource|string $parser The first parameter, parser, is a reference to the XML parser calling the handler. + * @param string $name The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. + * @param array $attribs The third parameter, attribs, contains an associative array with the element's attributes (if any). The keys of this array are the attribute names, the values are the attribute values. Attribute names are case-folded on the same criteria as element names. Attribute values are not case-folded. The original order of the attributes can be retrieved by walking through attribs the normal way, using each(). The first key in the array was the first attribute, and so on. + * @param array $ctm tranformation matrix for clipping mode (starting transformation matrix). * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected @@ -23978,7 +24102,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: break; } case 'linearGradient': { - if ($this->pdfa_mode) { + if ($this->pdfa_mode && $this->pdfa_version < 2) { break; } if (!isset($attribs['id'])) { @@ -24018,7 +24142,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: break; } case 'radialGradient': { - if ($this->pdfa_mode) { + if ($this->pdfa_mode && $this->pdfa_version < 2) { break; } if (!isset($attribs['id'])) { @@ -24452,8 +24576,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Sets the closing SVG element handler function for the XML parser. - * @param $parser (resource) The first parameter, parser, is a reference to the XML parser calling the handler. - * @param $name (string) The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. + * @param resource|string $parser The first parameter, parser, is a reference to the XML parser calling the handler. + * @param string $name The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected @@ -24559,8 +24683,8 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: /** * Sets the character data handler function for the XML parser. - * @param $parser (resource) The first parameter, parser, is a reference to the XML parser calling the handler. - * @param $data (string) The second parameter, data, contains the character data as a string. + * @param resource $parser The first parameter, parser, is a reference to the XML parser calling the handler. + * @param string $data The second parameter, data, contains the character data as a string. * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected @@ -24571,6 +24695,33 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: // --- END SVG METHODS ----------------------------------------------------- + /** + * Keeps files in memory, so it doesn't need to downloaded everytime in a loop + * @param string $file + * @return string + */ + protected function getCachedFileContents($file) + { + if (!isset($this->fileContentCache[$file])) { + $this->fileContentCache[$file] = TCPDF_STATIC::fileGetContents($file); + } + return $this->fileContentCache[$file]; + } + + /** + * Avoid multiple calls to an external server to see if a file exists + * @param string $file + * @return bool + */ + protected function fileExists($file) + { + if (isset($this->fileContentCache[$file]) || false !== $this->getImageBuffer($file)) { + return true; + } + + return TCPDF_STATIC::file_exists($file); + } + } // END OF TCPDF CLASS //============================================================+ diff --git a/lib/combodo/tcpdf/tcpdf_barcodes_1d.php b/lib/combodo/tcpdf/tcpdf_barcodes_1d.php index 78bfc5b5b..10a79a72e 100644 --- a/lib/combodo/tcpdf/tcpdf_barcodes_1d.php +++ b/lib/combodo/tcpdf/tcpdf_barcodes_1d.php @@ -53,7 +53,7 @@ class TCPDFBarcode { * Array representation of barcode. * @protected */ - protected $barcode_array; + protected $barcode_array = array(); /** * This is the class constructor. @@ -66,8 +66,8 @@ class TCPDFBarcode { *
                    • $arrcode['bcode'][$k]['w'] bar width in units.
                    • *
                    • $arrcode['bcode'][$k]['h'] bar height in units.
                    • *
                    • $arrcode['bcode'][$k]['p'] bar top position (0 = top, 1 = middle)
                    - * @param $code (string) code to print - * @param $type (string) type of barcode:
                    • C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
                    • C39+ : CODE 39 with checksum
                    • C39E : CODE 39 EXTENDED
                    • C39E+ : CODE 39 EXTENDED + CHECKSUM
                    • C93 : CODE 93 - USS-93
                    • S25 : Standard 2 of 5
                    • S25+ : Standard 2 of 5 + CHECKSUM
                    • I25 : Interleaved 2 of 5
                    • I25+ : Interleaved 2 of 5 + CHECKSUM
                    • C128 : CODE 128
                    • C128A : CODE 128 A
                    • C128B : CODE 128 B
                    • C128C : CODE 128 C
                    • EAN2 : 2-Digits UPC-Based Extension
                    • EAN5 : 5-Digits UPC-Based Extension
                    • EAN8 : EAN 8
                    • EAN13 : EAN 13
                    • UPCA : UPC-A
                    • UPCE : UPC-E
                    • MSI : MSI (Variation of Plessey code)
                    • MSI+ : MSI + CHECKSUM (modulo 11)
                    • POSTNET : POSTNET
                    • PLANET : PLANET
                    • RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
                    • KIX : KIX (Klant index - Customer index)
                    • IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200
                    • CODABAR : CODABAR
                    • CODE11 : CODE 11
                    • PHARMA : PHARMACODE
                    • PHARMA2T : PHARMACODE TWO-TRACKS
                    + * @param string $code code to print + * @param string $type type of barcode:
                    • C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
                    • C39+ : CODE 39 with checksum
                    • C39E : CODE 39 EXTENDED
                    • C39E+ : CODE 39 EXTENDED + CHECKSUM
                    • C93 : CODE 93 - USS-93
                    • S25 : Standard 2 of 5
                    • S25+ : Standard 2 of 5 + CHECKSUM
                    • I25 : Interleaved 2 of 5
                    • I25+ : Interleaved 2 of 5 + CHECKSUM
                    • C128 : CODE 128
                    • C128A : CODE 128 A
                    • C128B : CODE 128 B
                    • C128C : CODE 128 C
                    • EAN2 : 2-Digits UPC-Based Extension
                    • EAN5 : 5-Digits UPC-Based Extension
                    • EAN8 : EAN 8
                    • EAN13 : EAN 13
                    • UPCA : UPC-A
                    • UPCE : UPC-E
                    • MSI : MSI (Variation of Plessey code)
                    • MSI+ : MSI + CHECKSUM (modulo 11)
                    • POSTNET : POSTNET
                    • PLANET : PLANET
                    • RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
                    • KIX : KIX (Klant index - Customer index)
                    • IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200
                    • CODABAR : CODABAR
                    • CODE11 : CODE 11
                    • PHARMA : PHARMACODE
                    • PHARMA2T : PHARMACODE TWO-TRACKS
                    * @public */ public function __construct($code, $type) { @@ -85,9 +85,9 @@ class TCPDFBarcode { /** * Send barcode as SVG image object to the standard output. - * @param $w (int) Minimum width of a single bar in user units. - * @param $h (int) Height of barcode in user units. - * @param $color (string) Foreground color (in SVG format) for bar elements (background is transparent). + * @param int $w Minimum width of a single bar in user units. + * @param int $h Height of barcode in user units. + * @param string $color Foreground color (in SVG format) for bar elements (background is transparent). * @public */ public function getBarcodeSVG($w=2, $h=30, $color='black') { @@ -105,9 +105,9 @@ class TCPDFBarcode { /** * Return a SVG string representation of barcode. - * @param $w (int) Minimum width of a single bar in user units. - * @param $h (int) Height of barcode in user units. - * @param $color (string) Foreground color (in SVG format) for bar elements (background is transparent). + * @param int $w Minimum width of a single bar in user units. + * @param int $h Height of barcode in user units. + * @param string $color Foreground color (in SVG format) for bar elements (background is transparent). * @return string SVG code. * @public */ @@ -138,9 +138,9 @@ class TCPDFBarcode { /** * Return an HTML representation of barcode. - * @param $w (int) Width of a single bar element in pixels. - * @param $h (int) Height of a single bar element in pixels. - * @param $color (string) Foreground color for bar elements (background is transparent). + * @param int $w Width of a single bar element in pixels. + * @param int $h Height of a single bar element in pixels. + * @param string $color Foreground color for bar elements (background is transparent). * @return string HTML code. * @public */ @@ -164,9 +164,9 @@ class TCPDFBarcode { /** * Send a PNG image representation of barcode (requires GD or Imagick library). - * @param $w (int) Width of a single bar element in pixels. - * @param $h (int) Height of a single bar element in pixels. - * @param $color (array) RGB (0-255) foreground color for bar elements (background is transparent). + * @param int $w Width of a single bar element in pixels. + * @param int $h Height of a single bar element in pixels. + * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). * @public */ public function getBarcodePNG($w=2, $h=30, $color=array(0,0,0)) { @@ -183,10 +183,10 @@ class TCPDFBarcode { /** * Return a PNG image representation of barcode (requires GD or Imagick library). - * @param $w (int) Width of a single bar element in pixels. - * @param $h (int) Height of a single bar element in pixels. - * @param $color (array) RGB (0-255) foreground color for bar elements (background is transparent). - * @return image or false in case of error. + * @param int $w Width of a single bar element in pixels. + * @param int $h Height of a single bar element in pixels. + * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). + * @return string|Imagick|false image or false in case of error. * @public */ public function getBarcodePngData($w=2, $h=30, $color=array(0,0,0)) { @@ -241,9 +241,9 @@ class TCPDFBarcode { /** * Set the barcode. - * @param $code (string) code to print - * @param $type (string) type of barcode:
                    • C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
                    • C39+ : CODE 39 with checksum
                    • C39E : CODE 39 EXTENDED
                    • C39E+ : CODE 39 EXTENDED + CHECKSUM
                    • C93 : CODE 93 - USS-93
                    • S25 : Standard 2 of 5
                    • S25+ : Standard 2 of 5 + CHECKSUM
                    • I25 : Interleaved 2 of 5
                    • I25+ : Interleaved 2 of 5 + CHECKSUM
                    • C128 : CODE 128
                    • C128A : CODE 128 A
                    • C128B : CODE 128 B
                    • C128C : CODE 128 C
                    • EAN2 : 2-Digits UPC-Based Extension
                    • EAN5 : 5-Digits UPC-Based Extension
                    • EAN8 : EAN 8
                    • EAN13 : EAN 13
                    • UPCA : UPC-A
                    • UPCE : UPC-E
                    • MSI : MSI (Variation of Plessey code)
                    • MSI+ : MSI + CHECKSUM (modulo 11)
                    • POSTNET : POSTNET
                    • PLANET : PLANET
                    • RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
                    • KIX : KIX (Klant index - Customer index)
                    • IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200
                    • IMBPRE: Pre-processed Intelligent Mail Barcode - Onecode - USPS-B-3200, using only F,A,D,T letters
                    • CODABAR : CODABAR
                    • CODE11 : CODE 11
                    • PHARMA : PHARMACODE
                    • PHARMA2T : PHARMACODE TWO-TRACKS
                    - * @return array barcode array + * @param string $code code to print + * @param string $type type of barcode:
                    • C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
                    • C39+ : CODE 39 with checksum
                    • C39E : CODE 39 EXTENDED
                    • C39E+ : CODE 39 EXTENDED + CHECKSUM
                    • C93 : CODE 93 - USS-93
                    • S25 : Standard 2 of 5
                    • S25+ : Standard 2 of 5 + CHECKSUM
                    • I25 : Interleaved 2 of 5
                    • I25+ : Interleaved 2 of 5 + CHECKSUM
                    • C128 : CODE 128
                    • C128A : CODE 128 A
                    • C128B : CODE 128 B
                    • C128C : CODE 128 C
                    • EAN2 : 2-Digits UPC-Based Extension
                    • EAN5 : 5-Digits UPC-Based Extension
                    • EAN8 : EAN 8
                    • EAN13 : EAN 13
                    • UPCA : UPC-A
                    • UPCE : UPC-E
                    • MSI : MSI (Variation of Plessey code)
                    • MSI+ : MSI + CHECKSUM (modulo 11)
                    • POSTNET : POSTNET
                    • PLANET : PLANET
                    • RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
                    • KIX : KIX (Klant index - Customer index)
                    • IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200
                    • IMBPRE: Pre-processed Intelligent Mail Barcode - Onecode - USPS-B-3200, using only F,A,D,T letters
                    • CODABAR : CODABAR
                    • CODE11 : CODE 11
                    • PHARMA : PHARMACODE
                    • PHARMA2T : PHARMACODE TWO-TRACKS
                    + * @return void * @public */ public function setBarcode($code, $type) { @@ -373,7 +373,7 @@ class TCPDFBarcode { break; } default: { - $this->barcode_array = false; + $this->barcode_array = array(); $arrcode = false; break; } @@ -384,9 +384,9 @@ class TCPDFBarcode { /** * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. * General-purpose code in very wide use world-wide - * @param $code (string) code to represent. - * @param $extended (boolean) if true uses the extended mode. - * @param $checksum (boolean) if true add a checksum to the code. + * @param string $code code to represent. + * @param boolean $extended if true uses the extended mode. + * @param boolean $checksum if true add a checksum to the code. * @return array barcode representation. * @protected */ @@ -479,8 +479,8 @@ class TCPDFBarcode { /** * Encode a string to be used for CODE 39 Extended mode. - * @param $code (string) code to represent. - * @return encoded string. + * @param string $code code to represent. + * @return string encoded string. * @protected */ protected function encode_code39_ext($code) { @@ -530,8 +530,8 @@ class TCPDFBarcode { /** * Calculate CODE 39 checksum (modulo 43). - * @param $code (string) code to represent. - * @return char checksum. + * @param string $code code to represent. + * @return string char checksum. * @protected */ protected function checksum_code39($code) { @@ -553,7 +553,7 @@ class TCPDFBarcode { /** * CODE 93 - USS-93 * Compact code similar to Code 39 - * @param $code (string) code to represent. + * @param string $code code to represent. * @return array barcode representation. * @protected */ @@ -681,7 +681,7 @@ class TCPDFBarcode { /** * Calculate CODE 93 checksum (modulo 47). - * @param $code (string) code to represent. + * @param string $code code to represent. * @return string checksum code. * @protected */ @@ -730,7 +730,7 @@ class TCPDFBarcode { /** * Checksum for standard 2 of 5 barcodes. - * @param $code (string) code to process. + * @param string $code code to process. * @return int checksum. * @protected */ @@ -755,8 +755,8 @@ class TCPDFBarcode { * MSI. * Variation of Plessey code, with similar applications * Contains digits (0 to 9) and encodes the data only in the width of bars. - * @param $code (string) code to represent. - * @param $checksum (boolean) if true add a checksum to the code (modulo 11) + * @param string $code code to represent. + * @param boolean $checksum if true add a checksum to the code (modulo 11) * @return array barcode representation. * @protected */ @@ -814,8 +814,8 @@ class TCPDFBarcode { * Standard 2 of 5 barcodes. * Used in airline ticket marking, photofinishing * Contains digits (0 to 9) and encodes the data only in the width of bars. - * @param $code (string) code to represent. - * @param $checksum (boolean) if true add a checksum to the code + * @param string $code code to represent. + * @param boolean $checksum if true add a checksum to the code * @return array barcode representation. * @protected */ @@ -854,10 +854,9 @@ class TCPDFBarcode { } /** - * Convert binary barcode sequence to TCPDF barcode array. - * @param $seq (string) barcode as binary sequence. - * @param $bararray (array) barcode array. - * òparam array $bararray TCPDF barcode array to fill up + * Convert binary barcode sequence to WarnockPDF barcode array. + * @param string $seq barcode as binary sequence. + * @param array $bararray barcode array to fill up * @return array barcode representation. * @protected */ @@ -886,8 +885,8 @@ class TCPDFBarcode { * Interleaved 2 of 5 barcodes. * Compact numeric code, widely used in industry, air cargo * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces. - * @param $code (string) code to represent. - * @param $checksum (boolean) if true add a checksum to the code + * @param string $code code to represent. + * @param boolean $checksum if true add a checksum to the code * @return array barcode representation. * @protected */ @@ -938,7 +937,7 @@ class TCPDFBarcode { } else { $t = false; // space } - $w = $seq[$j]; + $w = (float)$seq[$j]; $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; @@ -950,8 +949,8 @@ class TCPDFBarcode { /** * C128 barcodes. * Very capable code, excellent density, high reliability; in very wide use world-wide - * @param $code (string) code to represent. - * @param $type (string) barcode type: A, B, C or empty for automatic switch (AUTO mode) + * @param string $code code to represent. + * @param string $type barcode type: A, B, C or empty for automatic switch (AUTO mode) * @return array barcode representation. * @protected */ @@ -1271,7 +1270,7 @@ class TCPDFBarcode { } else { $t = false; // space } - $w = $seq[$j]; + $w = (float)$seq[$j]; $bararray['bcode'][] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; } @@ -1281,7 +1280,7 @@ class TCPDFBarcode { /** * Split text code in A/B sequence for 128 code - * @param $code (string) code to split. + * @param string $code code to split. * @return array sequence * @protected */ @@ -1319,8 +1318,8 @@ class TCPDFBarcode { * EAN13: European Article Numbering international retail product code * UPC-A: Universal product code seen on almost all retail products in the USA and Canada * UPC-E: Short version of UPC symbol - * @param $code (string) code to represent. - * @param $len (string) barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A + * @param string $code code to represent. + * @param string $len barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A * @return array barcode representation. * @protected */ @@ -1512,8 +1511,8 @@ class TCPDFBarcode { * UPC-Based Extensions * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers * 5-Digit Ext.: Used to mark suggested retail price of books - * @param $code (string) code to represent. - * @param $len (string) barcode type: 2 = 2-Digit, 5 = 5-Digit + * @param string $code code to represent. + * @param string $len barcode type: 2 = 2-Digit, 5 = 5-Digit * @return array barcode representation. * @protected */ @@ -1587,8 +1586,8 @@ class TCPDFBarcode { /** * POSTNET and PLANET barcodes. * Used by U.S. Postal Service for automated mail sorting - * @param $code (string) zip code to represent. Must be a string containing a zip code of the form DDDDD or DDDDD-DDDD. - * @param $planet (boolean) if true print the PLANET barcode, otherwise print POSTNET + * @param string $code zip code to represent. Must be a string containing a zip code of the form DDDDD or DDDDD-DDDD. + * @param boolean $planet if true print the PLANET barcode, otherwise print POSTNET * @return array barcode representation. * @protected */ @@ -1660,8 +1659,8 @@ class TCPDFBarcode { * RMS4CC - CBC - KIX * RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index) * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service. - * @param $code (string) code to print - * @param $kix (boolean) if true prints the KIX variation (doesn't use the start and end symbols, and the checksum) - in this case the house number must be sufficed with an X and placed at the end of the code. + * @param string $code code to print + * @param boolean $kix if true prints the KIX variation (doesn't use the start and end symbols, and the checksum) - in this case the house number must be sufficed with an X and placed at the end of the code. * @return array barcode representation. * @protected */ @@ -1812,7 +1811,7 @@ class TCPDFBarcode { /** * CODABAR barcodes. * Older code often used in library systems, sometimes in blood banks - * @param $code (string) code to represent. + * @param string $code code to represent. * @return array barcode representation. * @protected */ @@ -1856,7 +1855,7 @@ class TCPDFBarcode { } else { $t = false; // space } - $w = $seq[$j]; + $w = (float)$seq[$j]; $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; @@ -1868,7 +1867,7 @@ class TCPDFBarcode { /** * CODE11 barcodes. * Used primarily for labeling telecommunications equipment - * @param $code (string) code to represent. + * @param string $code code to represent. * @return array barcode representation. * @protected */ @@ -1947,7 +1946,7 @@ class TCPDFBarcode { } else { $t = false; // space } - $w = $seq[$j]; + $w = (float)$seq[$j]; $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; @@ -1959,7 +1958,7 @@ class TCPDFBarcode { /** * Pharmacode * Contains digits (0 to 9) - * @param $code (string) code to represent. + * @param string $code code to represent. * @return array barcode representation. * @protected */ @@ -1985,7 +1984,7 @@ class TCPDFBarcode { /** * Pharmacode two-track * Contains digits (0 to 9) - * @param $code (string) code to represent. + * @param string $code code to represent. * @return array barcode representation. * @protected */ @@ -2047,7 +2046,7 @@ class TCPDFBarcode { * (requires PHP bcmath extension) * Intelligent Mail barcode is a 65-bar code for use on mail in the United States. * The fields are described as follows:
                    • The Barcode Identifier shall be assigned by USPS to encode the presort identification that is currently printed in human readable form on the optional endorsement line (OEL) as well as for future USPS use. This shall be two digits, with the second digit in the range of 0–4. The allowable encoding ranges shall be 00–04, 10–14, 20–24, 30–34, 40–44, 50–54, 60–64, 70–74, 80–84, and 90–94.
                    • The Service Type Identifier shall be assigned by USPS for any combination of services requested on the mailpiece. The allowable encoding range shall be 000http://it2.php.net/manual/en/function.dechex.php–999. Each 3-digit value shall correspond to a particular mail class with a particular combination of service(s). Each service program, such as OneCode Confirm and OneCode ACS, shall provide the list of Service Type Identifier values.
                    • The Mailer or Customer Identifier shall be assigned by USPS as a unique, 6 or 9 digit number that identifies a business entity. The allowable encoding range for the 6 digit Mailer ID shall be 000000- 899999, while the allowable encoding range for the 9 digit Mailer ID shall be 900000000-999999999.
                    • The Serial or Sequence Number shall be assigned by the mailer for uniquely identifying and tracking mailpieces. The allowable encoding range shall be 000000000–999999999 when used with a 6 digit Mailer ID and 000000-999999 when used with a 9 digit Mailer ID. e. The Delivery Point ZIP Code shall be assigned by the mailer for routing the mailpiece. This shall replace POSTNET for routing the mailpiece to its final delivery point. The length may be 0, 5, 9, or 11 digits. The allowable encoding ranges shall be no ZIP Code, 00000–99999, 000000000–999999999, and 00000000000–99999999999.
                    - * @param $code (string) code to print, separate the ZIP (routing code) from the rest using a minus char '-' (BarcodeID_ServiceTypeID_MailerID_SerialNumber-RoutingCode) + * @param string $code code to print, separate the ZIP (routing code) from the rest using a minus char '-' (BarcodeID_ServiceTypeID_MailerID_SerialNumber-RoutingCode) * @return array barcode representation. * @protected */ @@ -2171,8 +2170,8 @@ class TCPDFBarcode { /** * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200 - * - * @param $code (string) pre-formatted IMB barcode (65 chars "FADT") + * + * @param string $code pre-formatted IMB barcode (65 chars "FADT") * @return array barcode representation. * @protected */ @@ -2223,7 +2222,7 @@ class TCPDFBarcode { /** * Convert large integer number to hexadecimal representation. * (requires PHP bcmath extension) - * @param $number (string) number to convert specified as a string + * @param string $number number to convert specified as a string * @return string hexadecimal representation */ public function dec_to_hex($number) { @@ -2247,7 +2246,7 @@ class TCPDFBarcode { /** * Convert large hexadecimal number to decimal representation (string). * (requires PHP bcmath extension) - * @param $hex (string) hexadecimal number to convert specified as a string + * @param string $hex hexadecimal number to convert specified as a string * @return string hexadecimal representation */ public function hex_to_dec($hex) { @@ -2263,7 +2262,7 @@ class TCPDFBarcode { /** * Intelligent Mail Barcode calculation of Frame Check Sequence - * @param $code_arr (string) array of hexadecimal values (13 bytes holding 102 bits right justified). + * @param string $code_arr array of hexadecimal values (13 bytes holding 102 bits right justified). * @return int 11 bit Frame Check Sequence as integer (decimal base) * @protected */ @@ -2299,7 +2298,7 @@ class TCPDFBarcode { /** * Reverse unsigned short value - * @param $num (int) value to reversr + * @param int $num value to reversr * @return int reversed value * @protected */ @@ -2315,8 +2314,8 @@ class TCPDFBarcode { /** * generate Nof13 tables used for Intelligent Mail Barcode - * @param $n (int) is the type of table: 2 for 2of13 table, 5 for 5of13table - * @param $size (int) size of table (78 for n=2 and 1287 for n=5) + * @param int $n is the type of table: 2 for 2of13 table, 5 for 5of13table + * @param int $size size of table (78 for n=2 and 1287 for n=5) * @return array requested table * @protected */ diff --git a/lib/combodo/tcpdf/tcpdf_barcodes_2d.php b/lib/combodo/tcpdf/tcpdf_barcodes_2d.php index 13e236552..730361bd8 100644 --- a/lib/combodo/tcpdf/tcpdf_barcodes_2d.php +++ b/lib/combodo/tcpdf/tcpdf_barcodes_2d.php @@ -53,7 +53,7 @@ class TCPDF2DBarcode { * Array representation of barcode. * @protected */ - protected $barcode_array = false; + protected $barcode_array = array(); /** * This is the class constructor. @@ -62,8 +62,8 @@ class TCPDF2DBarcode { *
                  • $arrcode['num_rows'] required number of rows
                  • *
                  • $arrcode['num_cols'] required number of columns
                  • *
                  • $arrcode['bcode'][$r][$c] value of the cell is $r row and $c column (0 = transparent, 1 = black)
                  - * @param $code (string) code to print - * @param $type (string) type of barcode:
                  • DATAMATRIX : Datamatrix (ISO/IEC 16022)
                  • PDF417 : PDF417 (ISO/IEC 15438:2006)
                  • PDF417,a,e,t,s,f,o0,o1,o2,o3,o4,o5,o6 : PDF417 with parameters: a = aspect ratio (width/height); e = error correction level (0-8); t = total number of macro segments; s = macro segment index (0-99998); f = file ID; o0 = File Name (text); o1 = Segment Count (numeric); o2 = Time Stamp (numeric); o3 = Sender (text); o4 = Addressee (text); o5 = File Size (numeric); o6 = Checksum (numeric). NOTES: Parameters t, s and f are required for a Macro Control Block, all other parametrs are optional. To use a comma character ',' on text options, replace it with the character 255: "\xff".
                  • QRCODE : QRcode Low error correction
                  • QRCODE,L : QRcode Low error correction
                  • QRCODE,M : QRcode Medium error correction
                  • QRCODE,Q : QRcode Better error correction
                  • QRCODE,H : QR-CODE Best error correction
                  • RAW: raw mode - comma-separad list of array rows
                  • RAW2: raw mode - array rows are surrounded by square parenthesis.
                  • TEST : Test matrix
                  + * @param string $code code to print + * @param string $type type of barcode:
                  • DATAMATRIX : Datamatrix (ISO/IEC 16022)
                  • PDF417 : PDF417 (ISO/IEC 15438:2006)
                  • PDF417,a,e,t,s,f,o0,o1,o2,o3,o4,o5,o6 : PDF417 with parameters: a = aspect ratio (width/height); e = error correction level (0-8); t = total number of macro segments; s = macro segment index (0-99998); f = file ID; o0 = File Name (text); o1 = Segment Count (numeric); o2 = Time Stamp (numeric); o3 = Sender (text); o4 = Addressee (text); o5 = File Size (numeric); o6 = Checksum (numeric). NOTES: Parameters t, s and f are required for a Macro Control Block, all other parameters are optional. To use a comma character ',' on text options, replace it with the character 255: "\xff".
                  • QRCODE : QRcode Low error correction
                  • QRCODE,L : QRcode Low error correction
                  • QRCODE,M : QRcode Medium error correction
                  • QRCODE,Q : QRcode Better error correction
                  • QRCODE,H : QR-CODE Best error correction
                  • RAW: raw mode - comma-separad list of array rows
                  • RAW2: raw mode - array rows are surrounded by square parenthesis.
                  • TEST : Test matrix
                  */ public function __construct($code, $type) { $this->setBarcode($code, $type); @@ -79,9 +79,9 @@ class TCPDF2DBarcode { /** * Send barcode as SVG image object to the standard output. - * @param $w (int) Width of a single rectangle element in user units. - * @param $h (int) Height of a single rectangle element in user units. - * @param $color (string) Foreground color (in SVG format) for bar elements (background is transparent). + * @param int $w Width of a single rectangle element in user units. + * @param int $h Height of a single rectangle element in user units. + * @param string $color Foreground color (in SVG format) for bar elements (background is transparent). * @public */ public function getBarcodeSVG($w=3, $h=3, $color='black') { @@ -99,9 +99,9 @@ class TCPDF2DBarcode { /** * Return a SVG string representation of barcode. - * @param $w (int) Width of a single rectangle element in user units. - * @param $h (int) Height of a single rectangle element in user units. - * @param $color (string) Foreground color (in SVG format) for bar elements (background is transparent). + * @param int $w Width of a single rectangle element in user units. + * @param int $h Height of a single rectangle element in user units. + * @param string $color Foreground color (in SVG format) for bar elements (background is transparent). * @return string SVG code. * @public */ @@ -135,9 +135,9 @@ class TCPDF2DBarcode { /** * Return an HTML representation of barcode. - * @param $w (int) Width of a single rectangle element in pixels. - * @param $h (int) Height of a single rectangle element in pixels. - * @param $color (string) Foreground color for bar elements (background is transparent). + * @param int $w Width of a single rectangle element in pixels. + * @param int $h Height of a single rectangle element in pixels. + * @param string $color Foreground color for bar elements (background is transparent). * @return string HTML code. * @public */ @@ -164,9 +164,9 @@ class TCPDF2DBarcode { /** * Send a PNG image representation of barcode (requires GD or Imagick library). - * @param $w (int) Width of a single rectangle element in pixels. - * @param $h (int) Height of a single rectangle element in pixels. - * @param $color (array) RGB (0-255) foreground color for bar elements (background is transparent). + * @param int $w Width of a single rectangle element in pixels. + * @param int $h Height of a single rectangle element in pixels. + * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). * @public */ public function getBarcodePNG($w=3, $h=3, $color=array(0,0,0)) { @@ -184,10 +184,10 @@ class TCPDF2DBarcode { /** * Return a PNG image representation of barcode (requires GD or Imagick library). - * @param $w (int) Width of a single rectangle element in pixels. - * @param $h (int) Height of a single rectangle element in pixels. - * @param $color (array) RGB (0-255) foreground color for bar elements (background is transparent). - * @return image or false in case of error. + * @param int $w Width of a single rectangle element in pixels. + * @param int $h Height of a single rectangle element in pixels. + * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). + * @return string|Imagick|false image or false in case of error. * @public */ public function getBarcodePngData($w=3, $h=3, $color=array(0,0,0)) { @@ -245,9 +245,9 @@ class TCPDF2DBarcode { /** * Set the barcode. - * @param $code (string) code to print - * @param $type (string) type of barcode:
                  • DATAMATRIX : Datamatrix (ISO/IEC 16022)
                  • PDF417 : PDF417 (ISO/IEC 15438:2006)
                  • PDF417,a,e,t,s,f,o0,o1,o2,o3,o4,o5,o6 : PDF417 with parameters: a = aspect ratio (width/height); e = error correction level (0-8); t = total number of macro segments; s = macro segment index (0-99998); f = file ID; o0 = File Name (text); o1 = Segment Count (numeric); o2 = Time Stamp (numeric); o3 = Sender (text); o4 = Addressee (text); o5 = File Size (numeric); o6 = Checksum (numeric). NOTES: Parameters t, s and f are required for a Macro Control Block, all other parametrs are optional. To use a comma character ',' on text options, replace it with the character 255: "\xff".
                  • QRCODE : QRcode Low error correction
                  • QRCODE,L : QRcode Low error correction
                  • QRCODE,M : QRcode Medium error correction
                  • QRCODE,Q : QRcode Better error correction
                  • QRCODE,H : QR-CODE Best error correction
                  • RAW: raw mode - comma-separad list of array rows
                  • RAW2: raw mode - array rows are surrounded by square parenthesis.
                  • TEST : Test matrix
                  - * @return array + * @param string $code code to print + * @param string $type type of barcode:
                  • DATAMATRIX : Datamatrix (ISO/IEC 16022)
                  • PDF417 : PDF417 (ISO/IEC 15438:2006)
                  • PDF417,a,e,t,s,f,o0,o1,o2,o3,o4,o5,o6 : PDF417 with parameters: a = aspect ratio (width/height); e = error correction level (0-8); t = total number of macro segments; s = macro segment index (0-99998); f = file ID; o0 = File Name (text); o1 = Segment Count (numeric); o2 = Time Stamp (numeric); o3 = Sender (text); o4 = Addressee (text); o5 = File Size (numeric); o6 = Checksum (numeric). NOTES: Parameters t, s and f are required for a Macro Control Block, all other parameters are optional. To use a comma character ',' on text options, replace it with the character 255: "\xff".
                  • QRCODE : QRcode Low error correction
                  • QRCODE,L : QRcode Low error correction
                  • QRCODE,M : QRcode Medium error correction
                  • QRCODE,Q : QRcode Better error correction
                  • QRCODE,H : QR-CODE Best error correction
                  • RAW: raw mode - comma-separad list of array rows
                  • RAW2: raw mode - array rows are surrounded by square parenthesis.
                  • TEST : Test matrix
                  + * @return void */ public function setBarcode($code, $type) { $mode = explode(',', $type); @@ -338,7 +338,7 @@ class TCPDF2DBarcode { break; } default: { - $this->barcode_array = false; + $this->barcode_array = array(); } } } diff --git a/lib/combodo/tcpdf/tcpdf_import.php b/lib/combodo/tcpdf/tcpdf_import.php index 09d726ba0..cc6fda780 100644 --- a/lib/combodo/tcpdf/tcpdf_import.php +++ b/lib/combodo/tcpdf/tcpdf_import.php @@ -60,7 +60,7 @@ class TCPDF_IMPORT extends TCPDF { /** * Import an existing PDF document - * @param $filename (string) Filename of the PDF document to import. + * @param string $filename Filename of the PDF document to import. * @return true in case of success, false otherwise * @public * @since 1.0.000 (2011-05-24) diff --git a/lib/combodo/tcpdf/tcpdf_parser.php b/lib/combodo/tcpdf/tcpdf_parser.php index bd3d719c7..4156230a3 100644 --- a/lib/combodo/tcpdf/tcpdf_parser.php +++ b/lib/combodo/tcpdf/tcpdf_parser.php @@ -91,8 +91,8 @@ class TCPDF_PARSER { /** * Parse a PDF document an return an array of objects. - * @param $data (string) PDF data to parse. - * @param $cfg (array) Array of configuration parameters: + * @param string $data PDF data to parse. + * @param array $cfg Array of configuration parameters: * 'die_for_errors' : if true termitate the program execution in case of error, otherwise thows an exception; * 'ignore_filter_decoding_errors' : if true ignore filter decoding errors; * 'ignore_missing_filter_decoders' : if true ignore missing filter decoding errors. @@ -130,7 +130,7 @@ class TCPDF_PARSER { /** * Set the configuration parameters. - * @param $cfg (array) Array of configuration parameters: + * @param array $cfg Array of configuration parameters: * 'die_for_errors' : if true termitate the program execution in case of error, otherwise thows an exception; * 'ignore_filter_decoding_errors' : if true ignore filter decoding errors; * 'ignore_missing_filter_decoders' : if true ignore missing filter decoding errors. @@ -150,7 +150,7 @@ class TCPDF_PARSER { /** * Return an array of parsed PDF document objects. - * @return (array) Array of parsed PDF document objects. + * @return array Array of parsed PDF document objects. * @public * @since 1.0.000 (2011-06-26) */ @@ -160,9 +160,9 @@ class TCPDF_PARSER { /** * Get Cross-Reference (xref) table and trailer data from PDF document data. - * @param $offset (int) xref offset (if know). - * @param $xref (array) previous xref array (if any). - * @return Array containing xref and trailer data. + * @param int $offset xref offset (if know). + * @param array $xref previous xref array (if any). + * @return array containing xref and trailer data. * @protected * @since 1.0.000 (2011-05-24) */ @@ -202,9 +202,9 @@ class TCPDF_PARSER { /** * Decode the Cross-Reference section - * @param $startxref (int) Offset at which the xref section starts (position of the 'xref' keyword). - * @param $xref (array) Previous xref array (if any). - * @return Array containing xref and trailer data. + * @param int $startxref Offset at which the xref section starts (position of the 'xref' keyword). + * @param array $xref Previous xref array (if any). + * @return array containing xref and trailer data. * @protected * @since 1.0.000 (2011-06-20) */ @@ -274,9 +274,9 @@ class TCPDF_PARSER { /** * Decode the Cross-Reference Stream section - * @param $startxref (int) Offset at which the xref section starts. - * @param $xref (array) Previous xref array (if any). - * @return Array containing xref and trailer data. + * @param int $startxref Offset at which the xref section starts. + * @param array $xref Previous xref array (if any). + * @return array containing xref and trailer data. * @protected * @since 1.0.003 (2013-03-16) */ @@ -489,7 +489,7 @@ class TCPDF_PARSER { /** * Get object type, raw value and offset to next object - * @param $offset (int) Object offset. + * @param int $offset Object offset. * @return array containing object type, raw value and offset to next object * @protected * @since 1.0.000 (2011-06-20) @@ -667,9 +667,9 @@ class TCPDF_PARSER { /** * Get content of indirect object. - * @param $obj_ref (string) Object number and generation number separated by underscore character. - * @param $offset (int) Object offset. - * @param $decoding (boolean) If true decode streams. + * @param string $obj_ref Object number and generation number separated by underscore character. + * @param int $offset Object offset. + * @param boolean $decoding If true decode streams. * @return array containing object data. * @protected * @since 1.0.000 (2011-05-24) @@ -712,7 +712,7 @@ class TCPDF_PARSER { /** * Get the content of object, resolving indect object reference if necessary. - * @param $obj (string) Object value. + * @param string $obj Object value. * @return array containing object data. * @protected * @since 1.0.000 (2011-06-26) @@ -734,8 +734,8 @@ class TCPDF_PARSER { /** * Decode the specified stream. - * @param $sdic (array) Stream's dictionary array. - * @param $stream (string) Stream to decode. + * @param array $sdic Stream's dictionary array. + * @param string $stream Stream to decode. * @return array containing decoded stream data and remaining filters. * @protected * @since 1.0.000 (2011-06-22) @@ -796,7 +796,7 @@ class TCPDF_PARSER { /** * Throw an exception or print an error message and die if the K_TCPDF_PARSER_THROW_EXCEPTION_ERROR constant is set to true. - * @param $msg (string) The error message + * @param string $msg The error message * @public * @since 1.0.000 (2011-05-23) */ diff --git a/lib/composer/ClassLoader.php b/lib/composer/ClassLoader.php index 0cd6055d1..afef3fa2a 100644 --- a/lib/composer/ClassLoader.php +++ b/lib/composer/ClassLoader.php @@ -149,7 +149,7 @@ class ClassLoader /** * @return string[] Array of classname => path - * @psalm-var array + * @psalm-return array */ public function getClassMap() { diff --git a/lib/composer/InstalledVersions.php b/lib/composer/InstalledVersions.php index 7c5502ca4..41bc143c1 100644 --- a/lib/composer/InstalledVersions.php +++ b/lib/composer/InstalledVersions.php @@ -21,11 +21,26 @@ use Composer\Semver\VersionParser; * See also https://getcomposer.org/doc/07-runtime.md#installed-versions * * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final */ class InstalledVersions { + /** + * @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(); /** diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index b3955089f..359e17e04 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -2,7 +2,7 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( @@ -442,8 +442,74 @@ return array( 'DisplayableNode' => $baseDir . '/core/displayablegraph.class.inc.php', 'DisplayableRedundancyNode' => $baseDir . '/core/displayablegraph.class.inc.php', 'DivisionByZeroError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php', + 'Doctrine\\Common\\Lexer\\AbstractLexer' => $vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php', 'DownloadPage' => $baseDir . '/sources/application/WebPage/DownloadPage.php', 'EMail' => $baseDir . '/core/email.class.inc.php', + 'Egulias\\EmailValidator\\EmailLexer' => $vendorDir . '/egulias/email-validator/src/EmailLexer.php', + 'Egulias\\EmailValidator\\EmailParser' => $vendorDir . '/egulias/email-validator/src/EmailParser.php', + 'Egulias\\EmailValidator\\EmailValidator' => $vendorDir . '/egulias/email-validator/src/EmailValidator.php', + 'Egulias\\EmailValidator\\Exception\\AtextAfterCFWS' => $vendorDir . '/egulias/email-validator/src/Exception/AtextAfterCFWS.php', + 'Egulias\\EmailValidator\\Exception\\CRLFAtTheEnd' => $vendorDir . '/egulias/email-validator/src/Exception/CRLFAtTheEnd.php', + 'Egulias\\EmailValidator\\Exception\\CRLFX2' => $vendorDir . '/egulias/email-validator/src/Exception/CRLFX2.php', + 'Egulias\\EmailValidator\\Exception\\CRNoLF' => $vendorDir . '/egulias/email-validator/src/Exception/CRNoLF.php', + 'Egulias\\EmailValidator\\Exception\\CharNotAllowed' => $vendorDir . '/egulias/email-validator/src/Exception/CharNotAllowed.php', + 'Egulias\\EmailValidator\\Exception\\CommaInDomain' => $vendorDir . '/egulias/email-validator/src/Exception/CommaInDomain.php', + 'Egulias\\EmailValidator\\Exception\\ConsecutiveAt' => $vendorDir . '/egulias/email-validator/src/Exception/ConsecutiveAt.php', + 'Egulias\\EmailValidator\\Exception\\ConsecutiveDot' => $vendorDir . '/egulias/email-validator/src/Exception/ConsecutiveDot.php', + 'Egulias\\EmailValidator\\Exception\\DomainAcceptsNoMail' => $vendorDir . '/egulias/email-validator/src/Exception/DomainAcceptsNoMail.php', + 'Egulias\\EmailValidator\\Exception\\DomainHyphened' => $vendorDir . '/egulias/email-validator/src/Exception/DomainHyphened.php', + 'Egulias\\EmailValidator\\Exception\\DotAtEnd' => $vendorDir . '/egulias/email-validator/src/Exception/DotAtEnd.php', + 'Egulias\\EmailValidator\\Exception\\DotAtStart' => $vendorDir . '/egulias/email-validator/src/Exception/DotAtStart.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingAT' => $vendorDir . '/egulias/email-validator/src/Exception/ExpectingAT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingATEXT' => $vendorDir . '/egulias/email-validator/src/Exception/ExpectingATEXT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingCTEXT' => $vendorDir . '/egulias/email-validator/src/Exception/ExpectingCTEXT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingDTEXT' => $vendorDir . '/egulias/email-validator/src/Exception/ExpectingDTEXT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingDomainLiteralClose' => $vendorDir . '/egulias/email-validator/src/Exception/ExpectingDomainLiteralClose.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingQPair' => $vendorDir . '/egulias/email-validator/src/Exception/ExpectingQPair.php', + 'Egulias\\EmailValidator\\Exception\\InvalidEmail' => $vendorDir . '/egulias/email-validator/src/Exception/InvalidEmail.php', + 'Egulias\\EmailValidator\\Exception\\LocalOrReservedDomain' => $vendorDir . '/egulias/email-validator/src/Exception/LocalOrReservedDomain.php', + 'Egulias\\EmailValidator\\Exception\\NoDNSRecord' => $vendorDir . '/egulias/email-validator/src/Exception/NoDNSRecord.php', + 'Egulias\\EmailValidator\\Exception\\NoDomainPart' => $vendorDir . '/egulias/email-validator/src/Exception/NoDomainPart.php', + 'Egulias\\EmailValidator\\Exception\\NoLocalPart' => $vendorDir . '/egulias/email-validator/src/Exception/NoLocalPart.php', + 'Egulias\\EmailValidator\\Exception\\UnclosedComment' => $vendorDir . '/egulias/email-validator/src/Exception/UnclosedComment.php', + 'Egulias\\EmailValidator\\Exception\\UnclosedQuotedString' => $vendorDir . '/egulias/email-validator/src/Exception/UnclosedQuotedString.php', + 'Egulias\\EmailValidator\\Exception\\UnopenedComment' => $vendorDir . '/egulias/email-validator/src/Exception/UnopenedComment.php', + 'Egulias\\EmailValidator\\Parser\\DomainPart' => $vendorDir . '/egulias/email-validator/src/Parser/DomainPart.php', + 'Egulias\\EmailValidator\\Parser\\LocalPart' => $vendorDir . '/egulias/email-validator/src/Parser/LocalPart.php', + 'Egulias\\EmailValidator\\Parser\\Parser' => $vendorDir . '/egulias/email-validator/src/Parser/Parser.php', + 'Egulias\\EmailValidator\\Validation\\DNSCheckValidation' => $vendorDir . '/egulias/email-validator/src/Validation/DNSCheckValidation.php', + 'Egulias\\EmailValidator\\Validation\\EmailValidation' => $vendorDir . '/egulias/email-validator/src/Validation/EmailValidation.php', + 'Egulias\\EmailValidator\\Validation\\Error\\RFCWarnings' => $vendorDir . '/egulias/email-validator/src/Validation/Error/RFCWarnings.php', + 'Egulias\\EmailValidator\\Validation\\Error\\SpoofEmail' => $vendorDir . '/egulias/email-validator/src/Validation/Error/SpoofEmail.php', + 'Egulias\\EmailValidator\\Validation\\Exception\\EmptyValidationList' => $vendorDir . '/egulias/email-validator/src/Validation/Exception/EmptyValidationList.php', + 'Egulias\\EmailValidator\\Validation\\MultipleErrors' => $vendorDir . '/egulias/email-validator/src/Validation/MultipleErrors.php', + 'Egulias\\EmailValidator\\Validation\\MultipleValidationWithAnd' => $vendorDir . '/egulias/email-validator/src/Validation/MultipleValidationWithAnd.php', + 'Egulias\\EmailValidator\\Validation\\NoRFCWarningsValidation' => $vendorDir . '/egulias/email-validator/src/Validation/NoRFCWarningsValidation.php', + 'Egulias\\EmailValidator\\Validation\\RFCValidation' => $vendorDir . '/egulias/email-validator/src/Validation/RFCValidation.php', + 'Egulias\\EmailValidator\\Validation\\SpoofCheckValidation' => $vendorDir . '/egulias/email-validator/src/Validation/SpoofCheckValidation.php', + 'Egulias\\EmailValidator\\Warning\\AddressLiteral' => $vendorDir . '/egulias/email-validator/src/Warning/AddressLiteral.php', + 'Egulias\\EmailValidator\\Warning\\CFWSNearAt' => $vendorDir . '/egulias/email-validator/src/Warning/CFWSNearAt.php', + 'Egulias\\EmailValidator\\Warning\\CFWSWithFWS' => $vendorDir . '/egulias/email-validator/src/Warning/CFWSWithFWS.php', + 'Egulias\\EmailValidator\\Warning\\Comment' => $vendorDir . '/egulias/email-validator/src/Warning/Comment.php', + 'Egulias\\EmailValidator\\Warning\\DeprecatedComment' => $vendorDir . '/egulias/email-validator/src/Warning/DeprecatedComment.php', + 'Egulias\\EmailValidator\\Warning\\DomainLiteral' => $vendorDir . '/egulias/email-validator/src/Warning/DomainLiteral.php', + 'Egulias\\EmailValidator\\Warning\\DomainTooLong' => $vendorDir . '/egulias/email-validator/src/Warning/DomainTooLong.php', + 'Egulias\\EmailValidator\\Warning\\EmailTooLong' => $vendorDir . '/egulias/email-validator/src/Warning/EmailTooLong.php', + 'Egulias\\EmailValidator\\Warning\\IPV6BadChar' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6BadChar.php', + 'Egulias\\EmailValidator\\Warning\\IPV6ColonEnd' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6ColonEnd.php', + 'Egulias\\EmailValidator\\Warning\\IPV6ColonStart' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6ColonStart.php', + 'Egulias\\EmailValidator\\Warning\\IPV6Deprecated' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6Deprecated.php', + 'Egulias\\EmailValidator\\Warning\\IPV6DoubleColon' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6DoubleColon.php', + 'Egulias\\EmailValidator\\Warning\\IPV6GroupCount' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6GroupCount.php', + 'Egulias\\EmailValidator\\Warning\\IPV6MaxGroups' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6MaxGroups.php', + 'Egulias\\EmailValidator\\Warning\\LabelTooLong' => $vendorDir . '/egulias/email-validator/src/Warning/LabelTooLong.php', + 'Egulias\\EmailValidator\\Warning\\LocalTooLong' => $vendorDir . '/egulias/email-validator/src/Warning/LocalTooLong.php', + 'Egulias\\EmailValidator\\Warning\\NoDNSMXRecord' => $vendorDir . '/egulias/email-validator/src/Warning/NoDNSMXRecord.php', + 'Egulias\\EmailValidator\\Warning\\ObsoleteDTEXT' => $vendorDir . '/egulias/email-validator/src/Warning/ObsoleteDTEXT.php', + 'Egulias\\EmailValidator\\Warning\\QuotedPart' => $vendorDir . '/egulias/email-validator/src/Warning/QuotedPart.php', + 'Egulias\\EmailValidator\\Warning\\QuotedString' => $vendorDir . '/egulias/email-validator/src/Warning/QuotedString.php', + 'Egulias\\EmailValidator\\Warning\\TLD' => $vendorDir . '/egulias/email-validator/src/Warning/TLD.php', + 'Egulias\\EmailValidator\\Warning\\Warning' => $vendorDir . '/egulias/email-validator/src/Warning/Warning.php', 'Error' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/Error.php', 'ErrorPage' => $baseDir . '/sources/application/WebPage/ErrorPage.php', 'Event' => $baseDir . '/core/event.class.inc.php', @@ -533,6 +599,7 @@ return array( 'NewObjectMenuNode' => $baseDir . '/application/menunode.class.inc.php', 'NewsroomProviderBase' => $baseDir . '/application/newsroomprovider.class.inc.php', 'NiceWebPage' => $baseDir . '/sources/application/WebPage/NiceWebPage.php', + 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'NotYetEvaluatedExpression' => $baseDir . '/core/oql/expression.class.inc.php', 'OQLActualClassTreeResolver' => $baseDir . '/core/oqlactualclasstreeresolver.class.inc.php', 'OQLClassNode' => $baseDir . '/core/oqlclassnode.class.inc.php', @@ -588,6 +655,8 @@ return array( 'PhpParser\\Builder\\ClassConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php', 'PhpParser\\Builder\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php', 'PhpParser\\Builder\\Declaration' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php', + 'PhpParser\\Builder\\EnumCase' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php', + 'PhpParser\\Builder\\Enum_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Enum_.php', 'PhpParser\\Builder\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php', 'PhpParser\\Builder\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php', 'PhpParser\\Builder\\Interface_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php', @@ -617,6 +686,7 @@ return array( 'PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\CoaleseEqualTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\EnumTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php', + 'PhpParser\\Lexer\\TokenEmulator\\ExplicitOctalEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\FlexibleDocStringEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\FnTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php', @@ -644,6 +714,7 @@ return array( 'PhpParser\\Node\\Arg' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Arg.php', 'PhpParser\\Node\\Attribute' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Attribute.php', 'PhpParser\\Node\\AttributeGroup' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php', + 'PhpParser\\Node\\ComplexType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/ComplexType.php', 'PhpParser\\Node\\Const_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Const_.php', 'PhpParser\\Node\\Expr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr.php', 'PhpParser\\Node\\Expr\\ArrayDimFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php', @@ -696,6 +767,7 @@ return array( 'PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', 'PhpParser\\Node\\Expr\\BitwiseNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php', 'PhpParser\\Node\\Expr\\BooleanNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php', + 'PhpParser\\Node\\Expr\\CallLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php', 'PhpParser\\Node\\Expr\\Cast' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php', 'PhpParser\\Node\\Expr\\Cast\\Array_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php', 'PhpParser\\Node\\Expr\\Cast\\Bool_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php', @@ -742,6 +814,7 @@ return array( 'PhpParser\\Node\\Expr\\Yield_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php', 'PhpParser\\Node\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php', 'PhpParser\\Node\\Identifier' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Identifier.php', + 'PhpParser\\Node\\IntersectionType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php', 'PhpParser\\Node\\MatchArm' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/MatchArm.php', 'PhpParser\\Node\\Name' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name.php', 'PhpParser\\Node\\Name\\FullyQualified' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php', @@ -815,6 +888,7 @@ return array( 'PhpParser\\Node\\Stmt\\While_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php', 'PhpParser\\Node\\UnionType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/UnionType.php', 'PhpParser\\Node\\VarLikeIdentifier' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php', + 'PhpParser\\Node\\VariadicPlaceholder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php', 'PhpParser\\Parser' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser.php', 'PhpParser\\ParserAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php', 'PhpParser\\ParserFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserFactory.php', @@ -884,13 +958,29 @@ return array( 'ScalarOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', 'ScssPhp\\ScssPhp\\Base\\Range' => $vendorDir . '/scssphp/scssphp/src/Base/Range.php', 'ScssPhp\\ScssPhp\\Block' => $vendorDir . '/scssphp/scssphp/src/Block.php', + 'ScssPhp\\ScssPhp\\Block\\AtRootBlock' => $vendorDir . '/scssphp/scssphp/src/Block/AtRootBlock.php', + 'ScssPhp\\ScssPhp\\Block\\CallableBlock' => $vendorDir . '/scssphp/scssphp/src/Block/CallableBlock.php', + 'ScssPhp\\ScssPhp\\Block\\ContentBlock' => $vendorDir . '/scssphp/scssphp/src/Block/ContentBlock.php', + 'ScssPhp\\ScssPhp\\Block\\DirectiveBlock' => $vendorDir . '/scssphp/scssphp/src/Block/DirectiveBlock.php', + 'ScssPhp\\ScssPhp\\Block\\EachBlock' => $vendorDir . '/scssphp/scssphp/src/Block/EachBlock.php', + 'ScssPhp\\ScssPhp\\Block\\ElseBlock' => $vendorDir . '/scssphp/scssphp/src/Block/ElseBlock.php', + 'ScssPhp\\ScssPhp\\Block\\ElseifBlock' => $vendorDir . '/scssphp/scssphp/src/Block/ElseifBlock.php', + 'ScssPhp\\ScssPhp\\Block\\ForBlock' => $vendorDir . '/scssphp/scssphp/src/Block/ForBlock.php', + 'ScssPhp\\ScssPhp\\Block\\IfBlock' => $vendorDir . '/scssphp/scssphp/src/Block/IfBlock.php', + 'ScssPhp\\ScssPhp\\Block\\MediaBlock' => $vendorDir . '/scssphp/scssphp/src/Block/MediaBlock.php', + 'ScssPhp\\ScssPhp\\Block\\NestedPropertyBlock' => $vendorDir . '/scssphp/scssphp/src/Block/NestedPropertyBlock.php', + 'ScssPhp\\ScssPhp\\Block\\WhileBlock' => $vendorDir . '/scssphp/scssphp/src/Block/WhileBlock.php', 'ScssPhp\\ScssPhp\\Cache' => $vendorDir . '/scssphp/scssphp/src/Cache.php', 'ScssPhp\\ScssPhp\\Colors' => $vendorDir . '/scssphp/scssphp/src/Colors.php', + 'ScssPhp\\ScssPhp\\CompilationResult' => $vendorDir . '/scssphp/scssphp/src/CompilationResult.php', 'ScssPhp\\ScssPhp\\Compiler' => $vendorDir . '/scssphp/scssphp/src/Compiler.php', + 'ScssPhp\\ScssPhp\\Compiler\\CachedResult' => $vendorDir . '/scssphp/scssphp/src/Compiler/CachedResult.php', 'ScssPhp\\ScssPhp\\Compiler\\Environment' => $vendorDir . '/scssphp/scssphp/src/Compiler/Environment.php', 'ScssPhp\\ScssPhp\\Exception\\CompilerException' => $vendorDir . '/scssphp/scssphp/src/Exception/CompilerException.php', 'ScssPhp\\ScssPhp\\Exception\\ParserException' => $vendorDir . '/scssphp/scssphp/src/Exception/ParserException.php', 'ScssPhp\\ScssPhp\\Exception\\RangeException' => $vendorDir . '/scssphp/scssphp/src/Exception/RangeException.php', + 'ScssPhp\\ScssPhp\\Exception\\SassException' => $vendorDir . '/scssphp/scssphp/src/Exception/SassException.php', + 'ScssPhp\\ScssPhp\\Exception\\SassScriptException' => $vendorDir . '/scssphp/scssphp/src/Exception/SassScriptException.php', 'ScssPhp\\ScssPhp\\Exception\\ServerException' => $vendorDir . '/scssphp/scssphp/src/Exception/ServerException.php', 'ScssPhp\\ScssPhp\\Formatter' => $vendorDir . '/scssphp/scssphp/src/Formatter.php', 'ScssPhp\\ScssPhp\\Formatter\\Compact' => $vendorDir . '/scssphp/scssphp/src/Formatter/Compact.php', @@ -900,15 +990,22 @@ return array( 'ScssPhp\\ScssPhp\\Formatter\\Expanded' => $vendorDir . '/scssphp/scssphp/src/Formatter/Expanded.php', 'ScssPhp\\ScssPhp\\Formatter\\Nested' => $vendorDir . '/scssphp/scssphp/src/Formatter/Nested.php', 'ScssPhp\\ScssPhp\\Formatter\\OutputBlock' => $vendorDir . '/scssphp/scssphp/src/Formatter/OutputBlock.php', + 'ScssPhp\\ScssPhp\\Logger\\LoggerInterface' => $vendorDir . '/scssphp/scssphp/src/Logger/LoggerInterface.php', + 'ScssPhp\\ScssPhp\\Logger\\QuietLogger' => $vendorDir . '/scssphp/scssphp/src/Logger/QuietLogger.php', + 'ScssPhp\\ScssPhp\\Logger\\StreamLogger' => $vendorDir . '/scssphp/scssphp/src/Logger/StreamLogger.php', 'ScssPhp\\ScssPhp\\Node' => $vendorDir . '/scssphp/scssphp/src/Node.php', 'ScssPhp\\ScssPhp\\Node\\Number' => $vendorDir . '/scssphp/scssphp/src/Node/Number.php', + 'ScssPhp\\ScssPhp\\OutputStyle' => $vendorDir . '/scssphp/scssphp/src/OutputStyle.php', 'ScssPhp\\ScssPhp\\Parser' => $vendorDir . '/scssphp/scssphp/src/Parser.php', 'ScssPhp\\ScssPhp\\SourceMap\\Base64' => $vendorDir . '/scssphp/scssphp/src/SourceMap/Base64.php', 'ScssPhp\\ScssPhp\\SourceMap\\Base64VLQ' => $vendorDir . '/scssphp/scssphp/src/SourceMap/Base64VLQ.php', 'ScssPhp\\ScssPhp\\SourceMap\\SourceMapGenerator' => $vendorDir . '/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php', 'ScssPhp\\ScssPhp\\Type' => $vendorDir . '/scssphp/scssphp/src/Type.php', 'ScssPhp\\ScssPhp\\Util' => $vendorDir . '/scssphp/scssphp/src/Util.php', + 'ScssPhp\\ScssPhp\\Util\\Path' => $vendorDir . '/scssphp/scssphp/src/Util/Path.php', + 'ScssPhp\\ScssPhp\\ValueConverter' => $vendorDir . '/scssphp/scssphp/src/ValueConverter.php', 'ScssPhp\\ScssPhp\\Version' => $vendorDir . '/scssphp/scssphp/src/Version.php', + 'ScssPhp\\ScssPhp\\Warn' => $vendorDir . '/scssphp/scssphp/src/Warn.php', 'SearchMenuNode' => $baseDir . '/application/menunode.class.inc.php', 'SecurityException' => $baseDir . '/application/exceptions/SecurityException.php', 'SeparatorPopupMenuItem' => $baseDir . '/application/applicationextension.inc.php', @@ -1087,9 +1184,6 @@ return array( 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser' => $vendorDir . '/symfony/framework-bundle/Templating/TemplateNameParser.php', 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference' => $vendorDir . '/symfony/framework-bundle/Templating/TemplateReference.php', 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TimedPhpEngine' => $vendorDir . '/symfony/framework-bundle/Templating/TimedPhpEngine.php', - 'Symfony\\Bundle\\FrameworkBundle\\Test\\ForwardCompatTestTrait' => $vendorDir . '/symfony/framework-bundle/Test/ForwardCompatTestTrait.php', - 'Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => $vendorDir . '/symfony/framework-bundle/Test/KernelTestCase.php', - 'Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => $vendorDir . '/symfony/framework-bundle/Test/WebTestCase.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpExtractor' => $vendorDir . '/symfony/framework-bundle/Translation/PhpExtractor.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpStringTokenParser' => $vendorDir . '/symfony/framework-bundle/Translation/PhpStringTokenParser.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\TranslationLoader' => $vendorDir . '/symfony/framework-bundle/Translation/TranslationLoader.php', @@ -1894,7 +1988,6 @@ return array( 'Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => $vendorDir . '/symfony/var-dumper/Dumper/DataDumperInterface.php', 'Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => $vendorDir . '/symfony/var-dumper/Dumper/HtmlDumper.php', 'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => $vendorDir . '/symfony/var-dumper/Exception/ThrowingCasterException.php', - 'Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => $vendorDir . '/symfony/var-dumper/Test/VarDumperTestTrait.php', 'Symfony\\Component\\VarDumper\\VarDumper' => $vendorDir . '/symfony/var-dumper/VarDumper.php', 'Symfony\\Component\\Yaml\\Command\\LintCommand' => $vendorDir . '/symfony/yaml/Command/LintCommand.php', 'Symfony\\Component\\Yaml\\Dumper' => $vendorDir . '/symfony/yaml/Dumper.php', @@ -1910,9 +2003,16 @@ return array( 'Symfony\\Component\\Yaml\\Yaml' => $vendorDir . '/symfony/yaml/Yaml.php', 'Symfony\\Polyfill\\Apcu\\Apcu' => $vendorDir . '/symfony/polyfill-apcu/Apcu.php', 'Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/symfony/polyfill-ctype/Ctype.php', + 'Symfony\\Polyfill\\Iconv\\Iconv' => $vendorDir . '/symfony/polyfill-iconv/Iconv.php', + 'Symfony\\Polyfill\\Intl\\Idn\\Idn' => $vendorDir . '/symfony/polyfill-intl-idn/Idn.php', + 'Symfony\\Polyfill\\Intl\\Idn\\Info' => $vendorDir . '/symfony/polyfill-intl-idn/Info.php', + 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\DisallowedRanges' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php', + 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php', + 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php', 'Symfony\\Polyfill\\Php56\\Php56' => $vendorDir . '/symfony/polyfill-php56/Php56.php', 'Symfony\\Polyfill\\Php70\\Php70' => $vendorDir . '/symfony/polyfill-php70/Php70.php', + 'Symfony\\Polyfill\\Php72\\Php72' => $vendorDir . '/symfony/polyfill-php72/Php72.php', 'Symfony\\Polyfill\\Util\\Binary' => $vendorDir . '/symfony/polyfill-util/Binary.php', 'Symfony\\Polyfill\\Util\\BinaryNoFuncOverload' => $vendorDir . '/symfony/polyfill-util/BinaryNoFuncOverload.php', 'Symfony\\Polyfill\\Util\\BinaryOnFuncOverload' => $vendorDir . '/symfony/polyfill-util/BinaryOnFuncOverload.php', @@ -2101,6 +2201,8 @@ return array( 'Twig\\Source' => $vendorDir . '/twig/twig/src/Source.php', 'Twig\\Template' => $vendorDir . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => $vendorDir . '/twig/twig/src/TemplateWrapper.php', + 'Twig\\Test\\IntegrationTestCase' => $vendorDir . '/twig/twig/src/Test/IntegrationTestCase.php', + 'Twig\\Test\\NodeTestCase' => $vendorDir . '/twig/twig/src/Test/NodeTestCase.php', 'Twig\\Token' => $vendorDir . '/twig/twig/src/Token.php', 'Twig\\TokenParser\\AbstractTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/AbstractTokenParser.php', 'Twig\\TokenParser\\ApplyTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/ApplyTokenParser.php', @@ -2298,6 +2400,11 @@ return array( 'Twig_Test' => $vendorDir . '/twig/twig/lib/Twig/Test.php', 'Twig_TestCallableInterface' => $vendorDir . '/twig/twig/lib/Twig/TestCallableInterface.php', 'Twig_TestInterface' => $vendorDir . '/twig/twig/lib/Twig/TestInterface.php', + 'Twig_Test_Function' => $vendorDir . '/twig/twig/lib/Twig/Test/Function.php', + 'Twig_Test_IntegrationTestCase' => $vendorDir . '/twig/twig/lib/Twig/Test/IntegrationTestCase.php', + 'Twig_Test_Method' => $vendorDir . '/twig/twig/lib/Twig/Test/Method.php', + 'Twig_Test_Node' => $vendorDir . '/twig/twig/lib/Twig/Test/Node.php', + 'Twig_Test_NodeTestCase' => $vendorDir . '/twig/twig/lib/Twig/Test/NodeTestCase.php', 'Twig_Token' => $vendorDir . '/twig/twig/lib/Twig/Token.php', 'Twig_TokenParser' => $vendorDir . '/twig/twig/lib/Twig/TokenParser.php', 'Twig_TokenParserBroker' => $vendorDir . '/twig/twig/lib/Twig/TokenParserBroker.php', diff --git a/lib/composer/autoload_files.php b/lib/composer/autoload_files.php index 65bc196d3..183395d1f 100644 --- a/lib/composer/autoload_files.php +++ b/lib/composer/autoload_files.php @@ -2,16 +2,20 @@ // autoload_files.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( - '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php', '023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php', - '32dcc8afd4335739640db7d200c1971d' => $vendorDir . '/symfony/polyfill-apcu/bootstrap.php', 'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php', + 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', + '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', + 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', + '32dcc8afd4335739640db7d200c1971d' => $vendorDir . '/symfony/polyfill-apcu/bootstrap.php', + 'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php', '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', '2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php', ); diff --git a/lib/composer/autoload_namespaces.php b/lib/composer/autoload_namespaces.php index d12922d08..e6117c750 100644 --- a/lib/composer/autoload_namespaces.php +++ b/lib/composer/autoload_namespaces.php @@ -2,7 +2,7 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/lib/composer/autoload_psr4.php b/lib/composer/autoload_psr4.php index 20234ce5e..7d6039aea 100644 --- a/lib/composer/autoload_psr4.php +++ b/lib/composer/autoload_psr4.php @@ -2,15 +2,19 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( 'Twig\\' => array($vendorDir . '/twig/twig/src'), 'Symfony\\Polyfill\\Util\\' => array($vendorDir . '/symfony/polyfill-util'), + 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), 'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'), 'Symfony\\Polyfill\\Php56\\' => array($vendorDir . '/symfony/polyfill-php56'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), + 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'), + 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'), + 'Symfony\\Polyfill\\Iconv\\' => array($vendorDir . '/symfony/polyfill-iconv'), 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), 'Symfony\\Polyfill\\Apcu\\' => array($vendorDir . '/symfony/polyfill-apcu'), 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), @@ -41,4 +45,6 @@ return array( 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), 'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), 'Pelago\\' => array($vendorDir . '/pelago/emogrifier/src'), + 'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/src'), + 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer'), ); diff --git a/lib/composer/autoload_real.php b/lib/composer/autoload_real.php index 661cd2543..752e35fbd 100644 --- a/lib/composer/autoload_real.php +++ b/lib/composer/autoload_real.php @@ -25,33 +25,20 @@ class ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b require __DIR__ . '/platform_check.php'; spl_autoload_register(array('ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); spl_autoload_unregister(array('ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b', 'loadClassLoader')); $includePaths = require __DIR__ . '/include_paths.php'; $includePaths[] = get_include_path(); set_include_path(implode(PATH_SEPARATOR, $includePaths)); - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require __DIR__ . '/autoload_static.php'; - - call_user_func(\Composer\Autoload\ComposerStaticInit0018331147de7601e7552f7da8e3bb8b::getInitializer($loader)); - } else { - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } + require __DIR__ . '/autoload_static.php'; + call_user_func(\Composer\Autoload\ComposerStaticInit0018331147de7601e7552f7da8e3bb8b::getInitializer($loader)); $loader->setClassMapAuthoritative(true); $loader->register(true); - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInit0018331147de7601e7552f7da8e3bb8b::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } + $includeFiles = \Composer\Autoload\ComposerStaticInit0018331147de7601e7552f7da8e3bb8b::$files; foreach ($includeFiles as $fileIdentifier => $file) { composerRequire0018331147de7601e7552f7da8e3bb8b($fileIdentifier, $file); } @@ -60,11 +47,16 @@ class ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b } } +/** + * @param string $fileIdentifier + * @param string $file + * @return void + */ function composerRequire0018331147de7601e7552f7da8e3bb8b($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; } } diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 6a613b4ff..731a2e214 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -7,12 +7,16 @@ namespace Composer\Autoload; class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b { public static $files = array ( - '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php', '023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php', - '32dcc8afd4335739640db7d200c1971d' => __DIR__ . '/..' . '/symfony/polyfill-apcu/bootstrap.php', 'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php', + 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', + '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', + 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', + '32dcc8afd4335739640db7d200c1971d' => __DIR__ . '/..' . '/symfony/polyfill-apcu/bootstrap.php', + 'def43f6c87e4f8dfd0c9e1b1bab14fe8' => __DIR__ . '/..' . '/symfony/polyfill-iconv/bootstrap.php', '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', '2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php', ); @@ -25,9 +29,13 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'S' => array ( 'Symfony\\Polyfill\\Util\\' => 22, + 'Symfony\\Polyfill\\Php72\\' => 23, 'Symfony\\Polyfill\\Php70\\' => 23, 'Symfony\\Polyfill\\Php56\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, + 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33, + 'Symfony\\Polyfill\\Intl\\Idn\\' => 26, + 'Symfony\\Polyfill\\Iconv\\' => 23, 'Symfony\\Polyfill\\Ctype\\' => 23, 'Symfony\\Polyfill\\Apcu\\' => 22, 'Symfony\\Component\\Yaml\\' => 23, @@ -62,6 +70,14 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'PhpParser\\' => 10, 'Pelago\\' => 7, ), + 'E' => + array ( + 'Egulias\\EmailValidator\\' => 23, + ), + 'D' => + array ( + 'Doctrine\\Common\\Lexer\\' => 22, + ), ); public static $prefixDirsPsr4 = array ( @@ -73,6 +89,10 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-util', ), + 'Symfony\\Polyfill\\Php72\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php72', + ), 'Symfony\\Polyfill\\Php70\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php70', @@ -85,6 +105,18 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', ), + 'Symfony\\Polyfill\\Intl\\Normalizer\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer', + ), + 'Symfony\\Polyfill\\Intl\\Idn\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn', + ), + 'Symfony\\Polyfill\\Iconv\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-iconv', + ), 'Symfony\\Polyfill\\Ctype\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', @@ -205,6 +237,14 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b array ( 0 => __DIR__ . '/..' . '/pelago/emogrifier/src', ), + 'Egulias\\EmailValidator\\' => + array ( + 0 => __DIR__ . '/..' . '/egulias/email-validator/src', + ), + 'Doctrine\\Common\\Lexer\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/lexer/lib/Doctrine/Common/Lexer', + ), ); public static $prefixesPsr0 = array ( @@ -672,8 +712,74 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'DisplayableNode' => __DIR__ . '/../..' . '/core/displayablegraph.class.inc.php', 'DisplayableRedundancyNode' => __DIR__ . '/../..' . '/core/displayablegraph.class.inc.php', 'DivisionByZeroError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php', + 'Doctrine\\Common\\Lexer\\AbstractLexer' => __DIR__ . '/..' . '/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php', 'DownloadPage' => __DIR__ . '/../..' . '/sources/application/WebPage/DownloadPage.php', 'EMail' => __DIR__ . '/../..' . '/core/email.class.inc.php', + 'Egulias\\EmailValidator\\EmailLexer' => __DIR__ . '/..' . '/egulias/email-validator/src/EmailLexer.php', + 'Egulias\\EmailValidator\\EmailParser' => __DIR__ . '/..' . '/egulias/email-validator/src/EmailParser.php', + 'Egulias\\EmailValidator\\EmailValidator' => __DIR__ . '/..' . '/egulias/email-validator/src/EmailValidator.php', + 'Egulias\\EmailValidator\\Exception\\AtextAfterCFWS' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/AtextAfterCFWS.php', + 'Egulias\\EmailValidator\\Exception\\CRLFAtTheEnd' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/CRLFAtTheEnd.php', + 'Egulias\\EmailValidator\\Exception\\CRLFX2' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/CRLFX2.php', + 'Egulias\\EmailValidator\\Exception\\CRNoLF' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/CRNoLF.php', + 'Egulias\\EmailValidator\\Exception\\CharNotAllowed' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/CharNotAllowed.php', + 'Egulias\\EmailValidator\\Exception\\CommaInDomain' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/CommaInDomain.php', + 'Egulias\\EmailValidator\\Exception\\ConsecutiveAt' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/ConsecutiveAt.php', + 'Egulias\\EmailValidator\\Exception\\ConsecutiveDot' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/ConsecutiveDot.php', + 'Egulias\\EmailValidator\\Exception\\DomainAcceptsNoMail' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/DomainAcceptsNoMail.php', + 'Egulias\\EmailValidator\\Exception\\DomainHyphened' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/DomainHyphened.php', + 'Egulias\\EmailValidator\\Exception\\DotAtEnd' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/DotAtEnd.php', + 'Egulias\\EmailValidator\\Exception\\DotAtStart' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/DotAtStart.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingAT' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/ExpectingAT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingATEXT' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/ExpectingATEXT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingCTEXT' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/ExpectingCTEXT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingDTEXT' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/ExpectingDTEXT.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingDomainLiteralClose' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/ExpectingDomainLiteralClose.php', + 'Egulias\\EmailValidator\\Exception\\ExpectingQPair' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/ExpectingQPair.php', + 'Egulias\\EmailValidator\\Exception\\InvalidEmail' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/InvalidEmail.php', + 'Egulias\\EmailValidator\\Exception\\LocalOrReservedDomain' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/LocalOrReservedDomain.php', + 'Egulias\\EmailValidator\\Exception\\NoDNSRecord' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/NoDNSRecord.php', + 'Egulias\\EmailValidator\\Exception\\NoDomainPart' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/NoDomainPart.php', + 'Egulias\\EmailValidator\\Exception\\NoLocalPart' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/NoLocalPart.php', + 'Egulias\\EmailValidator\\Exception\\UnclosedComment' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/UnclosedComment.php', + 'Egulias\\EmailValidator\\Exception\\UnclosedQuotedString' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/UnclosedQuotedString.php', + 'Egulias\\EmailValidator\\Exception\\UnopenedComment' => __DIR__ . '/..' . '/egulias/email-validator/src/Exception/UnopenedComment.php', + 'Egulias\\EmailValidator\\Parser\\DomainPart' => __DIR__ . '/..' . '/egulias/email-validator/src/Parser/DomainPart.php', + 'Egulias\\EmailValidator\\Parser\\LocalPart' => __DIR__ . '/..' . '/egulias/email-validator/src/Parser/LocalPart.php', + 'Egulias\\EmailValidator\\Parser\\Parser' => __DIR__ . '/..' . '/egulias/email-validator/src/Parser/Parser.php', + 'Egulias\\EmailValidator\\Validation\\DNSCheckValidation' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/DNSCheckValidation.php', + 'Egulias\\EmailValidator\\Validation\\EmailValidation' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/EmailValidation.php', + 'Egulias\\EmailValidator\\Validation\\Error\\RFCWarnings' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/Error/RFCWarnings.php', + 'Egulias\\EmailValidator\\Validation\\Error\\SpoofEmail' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/Error/SpoofEmail.php', + 'Egulias\\EmailValidator\\Validation\\Exception\\EmptyValidationList' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/Exception/EmptyValidationList.php', + 'Egulias\\EmailValidator\\Validation\\MultipleErrors' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/MultipleErrors.php', + 'Egulias\\EmailValidator\\Validation\\MultipleValidationWithAnd' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/MultipleValidationWithAnd.php', + 'Egulias\\EmailValidator\\Validation\\NoRFCWarningsValidation' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/NoRFCWarningsValidation.php', + 'Egulias\\EmailValidator\\Validation\\RFCValidation' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/RFCValidation.php', + 'Egulias\\EmailValidator\\Validation\\SpoofCheckValidation' => __DIR__ . '/..' . '/egulias/email-validator/src/Validation/SpoofCheckValidation.php', + 'Egulias\\EmailValidator\\Warning\\AddressLiteral' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/AddressLiteral.php', + 'Egulias\\EmailValidator\\Warning\\CFWSNearAt' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/CFWSNearAt.php', + 'Egulias\\EmailValidator\\Warning\\CFWSWithFWS' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/CFWSWithFWS.php', + 'Egulias\\EmailValidator\\Warning\\Comment' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/Comment.php', + 'Egulias\\EmailValidator\\Warning\\DeprecatedComment' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/DeprecatedComment.php', + 'Egulias\\EmailValidator\\Warning\\DomainLiteral' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/DomainLiteral.php', + 'Egulias\\EmailValidator\\Warning\\DomainTooLong' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/DomainTooLong.php', + 'Egulias\\EmailValidator\\Warning\\EmailTooLong' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/EmailTooLong.php', + 'Egulias\\EmailValidator\\Warning\\IPV6BadChar' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/IPV6BadChar.php', + 'Egulias\\EmailValidator\\Warning\\IPV6ColonEnd' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/IPV6ColonEnd.php', + 'Egulias\\EmailValidator\\Warning\\IPV6ColonStart' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/IPV6ColonStart.php', + 'Egulias\\EmailValidator\\Warning\\IPV6Deprecated' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/IPV6Deprecated.php', + 'Egulias\\EmailValidator\\Warning\\IPV6DoubleColon' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/IPV6DoubleColon.php', + 'Egulias\\EmailValidator\\Warning\\IPV6GroupCount' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/IPV6GroupCount.php', + 'Egulias\\EmailValidator\\Warning\\IPV6MaxGroups' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/IPV6MaxGroups.php', + 'Egulias\\EmailValidator\\Warning\\LabelTooLong' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/LabelTooLong.php', + 'Egulias\\EmailValidator\\Warning\\LocalTooLong' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/LocalTooLong.php', + 'Egulias\\EmailValidator\\Warning\\NoDNSMXRecord' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/NoDNSMXRecord.php', + 'Egulias\\EmailValidator\\Warning\\ObsoleteDTEXT' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/ObsoleteDTEXT.php', + 'Egulias\\EmailValidator\\Warning\\QuotedPart' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/QuotedPart.php', + 'Egulias\\EmailValidator\\Warning\\QuotedString' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/QuotedString.php', + 'Egulias\\EmailValidator\\Warning\\TLD' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/TLD.php', + 'Egulias\\EmailValidator\\Warning\\Warning' => __DIR__ . '/..' . '/egulias/email-validator/src/Warning/Warning.php', 'Error' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/Error.php', 'ErrorPage' => __DIR__ . '/../..' . '/sources/application/WebPage/ErrorPage.php', 'Event' => __DIR__ . '/../..' . '/core/event.class.inc.php', @@ -763,6 +869,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'NewObjectMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', 'NewsroomProviderBase' => __DIR__ . '/../..' . '/application/newsroomprovider.class.inc.php', 'NiceWebPage' => __DIR__ . '/../..' . '/sources/application/WebPage/NiceWebPage.php', + 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'NotYetEvaluatedExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', 'OQLActualClassTreeResolver' => __DIR__ . '/../..' . '/core/oqlactualclasstreeresolver.class.inc.php', 'OQLClassNode' => __DIR__ . '/../..' . '/core/oqlclassnode.class.inc.php', @@ -818,6 +925,8 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'PhpParser\\Builder\\ClassConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php', 'PhpParser\\Builder\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php', 'PhpParser\\Builder\\Declaration' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php', + 'PhpParser\\Builder\\EnumCase' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php', + 'PhpParser\\Builder\\Enum_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Enum_.php', 'PhpParser\\Builder\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php', 'PhpParser\\Builder\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php', 'PhpParser\\Builder\\Interface_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php', @@ -847,6 +956,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\CoaleseEqualTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\EnumTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php', + 'PhpParser\\Lexer\\TokenEmulator\\ExplicitOctalEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\FlexibleDocStringEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\FnTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php', 'PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php', @@ -874,6 +984,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'PhpParser\\Node\\Arg' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Arg.php', 'PhpParser\\Node\\Attribute' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Attribute.php', 'PhpParser\\Node\\AttributeGroup' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php', + 'PhpParser\\Node\\ComplexType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/ComplexType.php', 'PhpParser\\Node\\Const_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Const_.php', 'PhpParser\\Node\\Expr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr.php', 'PhpParser\\Node\\Expr\\ArrayDimFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php', @@ -926,6 +1037,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', 'PhpParser\\Node\\Expr\\BitwiseNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php', 'PhpParser\\Node\\Expr\\BooleanNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php', + 'PhpParser\\Node\\Expr\\CallLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php', 'PhpParser\\Node\\Expr\\Cast' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php', 'PhpParser\\Node\\Expr\\Cast\\Array_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php', 'PhpParser\\Node\\Expr\\Cast\\Bool_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php', @@ -972,6 +1084,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'PhpParser\\Node\\Expr\\Yield_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php', 'PhpParser\\Node\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php', 'PhpParser\\Node\\Identifier' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Identifier.php', + 'PhpParser\\Node\\IntersectionType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php', 'PhpParser\\Node\\MatchArm' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/MatchArm.php', 'PhpParser\\Node\\Name' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name.php', 'PhpParser\\Node\\Name\\FullyQualified' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php', @@ -1045,6 +1158,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'PhpParser\\Node\\Stmt\\While_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php', 'PhpParser\\Node\\UnionType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/UnionType.php', 'PhpParser\\Node\\VarLikeIdentifier' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php', + 'PhpParser\\Node\\VariadicPlaceholder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php', 'PhpParser\\Parser' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser.php', 'PhpParser\\ParserAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php', 'PhpParser\\ParserFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserFactory.php', @@ -1114,13 +1228,29 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'ScalarOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', 'ScssPhp\\ScssPhp\\Base\\Range' => __DIR__ . '/..' . '/scssphp/scssphp/src/Base/Range.php', 'ScssPhp\\ScssPhp\\Block' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block.php', + 'ScssPhp\\ScssPhp\\Block\\AtRootBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/AtRootBlock.php', + 'ScssPhp\\ScssPhp\\Block\\CallableBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/CallableBlock.php', + 'ScssPhp\\ScssPhp\\Block\\ContentBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/ContentBlock.php', + 'ScssPhp\\ScssPhp\\Block\\DirectiveBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/DirectiveBlock.php', + 'ScssPhp\\ScssPhp\\Block\\EachBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/EachBlock.php', + 'ScssPhp\\ScssPhp\\Block\\ElseBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/ElseBlock.php', + 'ScssPhp\\ScssPhp\\Block\\ElseifBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/ElseifBlock.php', + 'ScssPhp\\ScssPhp\\Block\\ForBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/ForBlock.php', + 'ScssPhp\\ScssPhp\\Block\\IfBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/IfBlock.php', + 'ScssPhp\\ScssPhp\\Block\\MediaBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/MediaBlock.php', + 'ScssPhp\\ScssPhp\\Block\\NestedPropertyBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/NestedPropertyBlock.php', + 'ScssPhp\\ScssPhp\\Block\\WhileBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/WhileBlock.php', 'ScssPhp\\ScssPhp\\Cache' => __DIR__ . '/..' . '/scssphp/scssphp/src/Cache.php', 'ScssPhp\\ScssPhp\\Colors' => __DIR__ . '/..' . '/scssphp/scssphp/src/Colors.php', + 'ScssPhp\\ScssPhp\\CompilationResult' => __DIR__ . '/..' . '/scssphp/scssphp/src/CompilationResult.php', 'ScssPhp\\ScssPhp\\Compiler' => __DIR__ . '/..' . '/scssphp/scssphp/src/Compiler.php', + 'ScssPhp\\ScssPhp\\Compiler\\CachedResult' => __DIR__ . '/..' . '/scssphp/scssphp/src/Compiler/CachedResult.php', 'ScssPhp\\ScssPhp\\Compiler\\Environment' => __DIR__ . '/..' . '/scssphp/scssphp/src/Compiler/Environment.php', 'ScssPhp\\ScssPhp\\Exception\\CompilerException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/CompilerException.php', 'ScssPhp\\ScssPhp\\Exception\\ParserException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/ParserException.php', 'ScssPhp\\ScssPhp\\Exception\\RangeException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/RangeException.php', + 'ScssPhp\\ScssPhp\\Exception\\SassException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/SassException.php', + 'ScssPhp\\ScssPhp\\Exception\\SassScriptException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/SassScriptException.php', 'ScssPhp\\ScssPhp\\Exception\\ServerException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/ServerException.php', 'ScssPhp\\ScssPhp\\Formatter' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter.php', 'ScssPhp\\ScssPhp\\Formatter\\Compact' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Compact.php', @@ -1130,15 +1260,22 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'ScssPhp\\ScssPhp\\Formatter\\Expanded' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Expanded.php', 'ScssPhp\\ScssPhp\\Formatter\\Nested' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Nested.php', 'ScssPhp\\ScssPhp\\Formatter\\OutputBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/OutputBlock.php', + 'ScssPhp\\ScssPhp\\Logger\\LoggerInterface' => __DIR__ . '/..' . '/scssphp/scssphp/src/Logger/LoggerInterface.php', + 'ScssPhp\\ScssPhp\\Logger\\QuietLogger' => __DIR__ . '/..' . '/scssphp/scssphp/src/Logger/QuietLogger.php', + 'ScssPhp\\ScssPhp\\Logger\\StreamLogger' => __DIR__ . '/..' . '/scssphp/scssphp/src/Logger/StreamLogger.php', 'ScssPhp\\ScssPhp\\Node' => __DIR__ . '/..' . '/scssphp/scssphp/src/Node.php', 'ScssPhp\\ScssPhp\\Node\\Number' => __DIR__ . '/..' . '/scssphp/scssphp/src/Node/Number.php', + 'ScssPhp\\ScssPhp\\OutputStyle' => __DIR__ . '/..' . '/scssphp/scssphp/src/OutputStyle.php', 'ScssPhp\\ScssPhp\\Parser' => __DIR__ . '/..' . '/scssphp/scssphp/src/Parser.php', 'ScssPhp\\ScssPhp\\SourceMap\\Base64' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/Base64.php', 'ScssPhp\\ScssPhp\\SourceMap\\Base64VLQ' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/Base64VLQ.php', 'ScssPhp\\ScssPhp\\SourceMap\\SourceMapGenerator' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php', 'ScssPhp\\ScssPhp\\Type' => __DIR__ . '/..' . '/scssphp/scssphp/src/Type.php', 'ScssPhp\\ScssPhp\\Util' => __DIR__ . '/..' . '/scssphp/scssphp/src/Util.php', + 'ScssPhp\\ScssPhp\\Util\\Path' => __DIR__ . '/..' . '/scssphp/scssphp/src/Util/Path.php', + 'ScssPhp\\ScssPhp\\ValueConverter' => __DIR__ . '/..' . '/scssphp/scssphp/src/ValueConverter.php', 'ScssPhp\\ScssPhp\\Version' => __DIR__ . '/..' . '/scssphp/scssphp/src/Version.php', + 'ScssPhp\\ScssPhp\\Warn' => __DIR__ . '/..' . '/scssphp/scssphp/src/Warn.php', 'SearchMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', 'SecurityException' => __DIR__ . '/../..' . '/application/exceptions/SecurityException.php', 'SeparatorPopupMenuItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', @@ -1317,9 +1454,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser' => __DIR__ . '/..' . '/symfony/framework-bundle/Templating/TemplateNameParser.php', 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference' => __DIR__ . '/..' . '/symfony/framework-bundle/Templating/TemplateReference.php', 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TimedPhpEngine' => __DIR__ . '/..' . '/symfony/framework-bundle/Templating/TimedPhpEngine.php', - 'Symfony\\Bundle\\FrameworkBundle\\Test\\ForwardCompatTestTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/ForwardCompatTestTrait.php', - 'Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/KernelTestCase.php', - 'Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/WebTestCase.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpExtractor' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/PhpExtractor.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpStringTokenParser' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/PhpStringTokenParser.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\TranslationLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/TranslationLoader.php', @@ -2124,7 +2258,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/DataDumperInterface.php', 'Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/HtmlDumper.php', 'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => __DIR__ . '/..' . '/symfony/var-dumper/Exception/ThrowingCasterException.php', - 'Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => __DIR__ . '/..' . '/symfony/var-dumper/Test/VarDumperTestTrait.php', 'Symfony\\Component\\VarDumper\\VarDumper' => __DIR__ . '/..' . '/symfony/var-dumper/VarDumper.php', 'Symfony\\Component\\Yaml\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/yaml/Command/LintCommand.php', 'Symfony\\Component\\Yaml\\Dumper' => __DIR__ . '/..' . '/symfony/yaml/Dumper.php', @@ -2140,9 +2273,16 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Symfony\\Component\\Yaml\\Yaml' => __DIR__ . '/..' . '/symfony/yaml/Yaml.php', 'Symfony\\Polyfill\\Apcu\\Apcu' => __DIR__ . '/..' . '/symfony/polyfill-apcu/Apcu.php', 'Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/symfony/polyfill-ctype/Ctype.php', + 'Symfony\\Polyfill\\Iconv\\Iconv' => __DIR__ . '/..' . '/symfony/polyfill-iconv/Iconv.php', + 'Symfony\\Polyfill\\Intl\\Idn\\Idn' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Idn.php', + 'Symfony\\Polyfill\\Intl\\Idn\\Info' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Info.php', + 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\DisallowedRanges' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php', + 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php', + 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php', 'Symfony\\Polyfill\\Php56\\Php56' => __DIR__ . '/..' . '/symfony/polyfill-php56/Php56.php', 'Symfony\\Polyfill\\Php70\\Php70' => __DIR__ . '/..' . '/symfony/polyfill-php70/Php70.php', + 'Symfony\\Polyfill\\Php72\\Php72' => __DIR__ . '/..' . '/symfony/polyfill-php72/Php72.php', 'Symfony\\Polyfill\\Util\\Binary' => __DIR__ . '/..' . '/symfony/polyfill-util/Binary.php', 'Symfony\\Polyfill\\Util\\BinaryNoFuncOverload' => __DIR__ . '/..' . '/symfony/polyfill-util/BinaryNoFuncOverload.php', 'Symfony\\Polyfill\\Util\\BinaryOnFuncOverload' => __DIR__ . '/..' . '/symfony/polyfill-util/BinaryOnFuncOverload.php', @@ -2331,6 +2471,8 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Twig\\Source' => __DIR__ . '/..' . '/twig/twig/src/Source.php', 'Twig\\Template' => __DIR__ . '/..' . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => __DIR__ . '/..' . '/twig/twig/src/TemplateWrapper.php', + 'Twig\\Test\\IntegrationTestCase' => __DIR__ . '/..' . '/twig/twig/src/Test/IntegrationTestCase.php', + 'Twig\\Test\\NodeTestCase' => __DIR__ . '/..' . '/twig/twig/src/Test/NodeTestCase.php', 'Twig\\Token' => __DIR__ . '/..' . '/twig/twig/src/Token.php', 'Twig\\TokenParser\\AbstractTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/AbstractTokenParser.php', 'Twig\\TokenParser\\ApplyTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/ApplyTokenParser.php', @@ -2528,6 +2670,11 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Twig_Test' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test.php', 'Twig_TestCallableInterface' => __DIR__ . '/..' . '/twig/twig/lib/Twig/TestCallableInterface.php', 'Twig_TestInterface' => __DIR__ . '/..' . '/twig/twig/lib/Twig/TestInterface.php', + 'Twig_Test_Function' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/Function.php', + 'Twig_Test_IntegrationTestCase' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/IntegrationTestCase.php', + 'Twig_Test_Method' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/Method.php', + 'Twig_Test_Node' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/Node.php', + 'Twig_Test_NodeTestCase' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/NodeTestCase.php', 'Twig_Token' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Token.php', 'Twig_TokenParser' => __DIR__ . '/..' . '/twig/twig/lib/Twig/TokenParser.php', 'Twig_TokenParserBroker' => __DIR__ . '/..' . '/twig/twig/lib/Twig/TokenParserBroker.php', diff --git a/lib/composer/include_paths.php b/lib/composer/include_paths.php index d4fb96718..af33c1491 100644 --- a/lib/composer/include_paths.php +++ b/lib/composer/include_paths.php @@ -2,7 +2,7 @@ // include_paths.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/lib/composer/installed.json b/lib/composer/installed.json index 36d4536cd..c572a6d3a 100644 --- a/lib/composer/installed.json +++ b/lib/composer/installed.json @@ -2,17 +2,17 @@ "packages": [ { "name": "combodo/tcpdf", - "version": "6.3.5", - "version_normalized": "6.3.5.0", + "version": "6.4.4", + "version_normalized": "6.4.4.0", "source": { "type": "git", "url": "https://github.com/combodo-itop-libs/TCPDF.git", - "reference": "aedd4b7b8cf7fcc24e617c405c9d3304150f4b94" + "reference": "0e31c013ccd000aa6762e9186778aa6e259ac8e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/combodo-itop-libs/TCPDF/zipball/aedd4b7b8cf7fcc24e617c405c9d3304150f4b94", - "reference": "aedd4b7b8cf7fcc24e617c405c9d3304150f4b94", + "url": "https://api.github.com/repos/combodo-itop-libs/TCPDF/zipball/0e31c013ccd000aa6762e9186778aa6e259ac8e8", + "reference": "0e31c013ccd000aa6762e9186778aa6e259ac8e8", "shasum": "" }, "require": { @@ -21,7 +21,7 @@ "replace": { "tecnickcom/tcpdf": "self.version" }, - "time": "2020-09-28T12:19:09+00:00", + "time": "2022-03-10T14:36:39+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -59,23 +59,191 @@ "email": "contact@combodo.com" } ], - "description": "TCPDF fork adding requirements for iTop: Specific fonts.", + "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", "homepage": "https://github.com/combodo-itop-libs/TCPDF", + "keywords": [ + "PDFD32000-2008", + "TCPDF", + "barcodes", + "datamatrix", + "pdf", + "pdf417", + "qrcode" + ], + "support": { + "source": "https://github.com/combodo-itop-libs/TCPDF/tree/6.4.4" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20tcpdf%20project", + "type": "custom" + } + ], "install-path": "../combodo/tcpdf" }, { - "name": "nikic/php-parser", - "version": "v4.12.0", - "version_normalized": "4.12.0.0", + "name": "doctrine/lexer", + "version": "1.2.3", + "version_normalized": "1.2.3.0", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "6608f01670c3cc5079e18c1dab1104e002579143" + "url": "https://github.com/doctrine/lexer.git", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6608f01670c3cc5079e18c1dab1104e002579143", - "reference": "6608f01670c3cc5079e18c1dab1104e002579143", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.11" + }, + "time": "2022-02-28T11:07:21+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.3" + }, + "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%2Flexer", + "type": "tidelift" + } + ], + "install-path": "../doctrine/lexer" + }, + { + "name": "egulias/email-validator", + "version": "2.1.25", + "version_normalized": "2.1.25.0", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/0dbf5d78455d4d6a41d186da50adc1122ec066f4", + "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1.0.1", + "php": ">=5.5", + "symfony/polyfill-intl-idn": "^1.10" + }, + "require-dev": { + "dominicsayers/isemail": "^3.0.7", + "phpunit/phpunit": "^4.8.36|^7.5.15", + "satooshi/php-coveralls": "^1.0.1" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "time": "2020-12-29T14:50:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/2.1.25" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "install-path": "../egulias/email-validator" + }, + { + "name": "nikic/php-parser", + "version": "v4.13.2", + "version_normalized": "4.13.2.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077", "shasum": "" }, "require": { @@ -86,7 +254,7 @@ "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, - "time": "2021-07-21T10:44:31+00:00", + "time": "2021-11-30T19:35:32+00:00", "bin": [ "bin/php-parse" ], @@ -118,7 +286,7 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.12.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" }, "install-path": "../nikic/php-parser" }, @@ -701,17 +869,17 @@ }, { "name": "scssphp/scssphp", - "version": "1.0.6", - "version_normalized": "1.0.6.0", + "version": "v1.10.2", + "version_normalized": "1.10.2.0", "source": { "type": "git", "url": "https://github.com/scssphp/scssphp.git", - "reference": "5b3c9d704950d8f9637f5110c36c281ec47dc13c" + "reference": "387f4f4abf5d99f16be16314c5ab856f81c82f46" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/scssphp/scssphp/zipball/5b3c9d704950d8f9637f5110c36c281ec47dc13c", - "reference": "5b3c9d704950d8f9637f5110c36c281ec47dc13c", + "url": "https://api.github.com/repos/scssphp/scssphp/zipball/387f4f4abf5d99f16be16314c5ab856f81c82f46", + "reference": "387f4f4abf5d99f16be16314c5ab856f81c82f46", "shasum": "" }, "require": { @@ -720,12 +888,21 @@ "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3", - "squizlabs/php_codesniffer": "~2.5", - "twbs/bootstrap": "~4.3", + "bamarni/composer-bin-plugin": "^1.4", + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4", + "sass/sass-spec": "*", + "squizlabs/php_codesniffer": "~3.5", + "symfony/phpunit-bridge": "^5.1", + "thoughtbot/bourbon": "^7.0", + "twbs/bootstrap": "~5.0", + "twbs/bootstrap4": "4.6.1", "zurb/foundation": "~6.5" }, - "time": "2019-12-12T05:00:52+00:00", + "suggest": { + "ext-iconv": "Can be used as fallback when ext-mbstring is not available", + "ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv" + }, + "time": "2022-03-02T21:15:09+00:00", "bin": [ "bin/pscss" ], @@ -761,35 +938,46 @@ "scss", "stylesheet" ], + "support": { + "issues": "https://github.com/scssphp/scssphp/issues", + "source": "https://github.com/scssphp/scssphp/tree/v1.10.2" + }, "install-path": "../scssphp/scssphp" }, { "name": "swiftmailer/swiftmailer", - "version": "v5.4.12", - "version_normalized": "5.4.12.0", + "version": "v6.3.0", + "version_normalized": "6.3.0.0", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "181b89f18a90f8925ef805f950d47a7190e9b950" + "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950", - "reference": "181b89f18a90f8925ef805f950d47a7190e9b950", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/8a5d5072dca8f48460fce2f4131fcc495eec654c", + "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c", "shasum": "" }, "require": { - "php": ">=5.3.3" + "egulias/email-validator": "^2.0|^3.1", + "php": ">=7.0.0", + "symfony/polyfill-iconv": "^1.0", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" }, "require-dev": { - "mockery/mockery": "~0.9.1", - "symfony/phpunit-bridge": "~3.2" + "mockery/mockery": "^1.0", + "symfony/phpunit-bridge": "^4.4|^5.4" }, - "time": "2018-07-31T09:26:32+00:00", + "suggest": { + "ext-intl": "Needed to support internationalized email addresses" + }, + "time": "2021-10-18T15:26:12+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "5.4-dev" + "dev-master": "6.2-dev" } }, "installation-source": "dist", @@ -818,6 +1006,21 @@ "mail", "mailer" ], + "support": { + "issues": "https://github.com/swiftmailer/swiftmailer/issues", + "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.3.0" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/swiftmailer/swiftmailer", + "type": "tidelift" + } + ], + "abandoned": "symfony/mailer", "install-path": "../swiftmailer/swiftmailer" }, { @@ -2113,6 +2316,269 @@ ], "install-path": "../symfony/polyfill-ctype" }, + { + "name": "symfony/polyfill-iconv", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-iconv.git", + "reference": "f1aed619e28cb077fc83fac8c4c0383578356e40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/f1aed619e28cb077fc83fac8c4c0383578356e40", + "reference": "f1aed619e28cb077fc83fac8c4c0383578356e40", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-iconv": "*" + }, + "suggest": { + "ext-iconv": "For best performance" + }, + "time": "2022-01-04T09:04:05+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Iconv\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Iconv extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "iconv", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-iconv" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "749045c69efb97c70d25d7463abba812e91f3a44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/749045c69efb97c70d25d7463abba812e91f3a44", + "reference": "749045c69efb97c70d25d7463abba812e91f3a44", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-intl-normalizer": "^1.10", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "time": "2021-09-14T14:02:44+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-intl-idn" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "time": "2021-02-19T12:13:01+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-intl-normalizer" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.19.0", @@ -2359,6 +2825,85 @@ ], "install-path": "../symfony/polyfill-php70" }, + { + "name": "symfony/polyfill-php72", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2021-05-27T09:17:38+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php72" + }, { "name": "symfony/polyfill-util", "version": "v1.19.0", @@ -3030,17 +3575,17 @@ }, { "name": "twig/twig", - "version": "v1.42.4", - "version_normalized": "1.42.4.0", + "version": "v1.42.5", + "version_normalized": "1.42.5.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "e587180584c3d2d6cb864a0454e777bb6dcb6152" + "reference": "87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/e587180584c3d2d6cb864a0454e777bb6dcb6152", - "reference": "e587180584c3d2d6cb864a0454e777bb6dcb6152", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e", + "reference": "87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e", "shasum": "" }, "require": { @@ -3049,10 +3594,9 @@ }, "require-dev": { "psr/container": "^1.0", - "symfony/debug": "^3.4|^4.2", - "symfony/phpunit-bridge": "^4.4@dev|^5.0" + "symfony/phpunit-bridge": "^4.4|^5.0" }, - "time": "2019-11-11T16:49:32+00:00", + "time": "2020-02-11T05:59:23+00:00", "type": "library", "extra": { "branch-alias": { @@ -3081,7 +3625,6 @@ }, { "name": "Twig Team", - "homepage": "https://twig.symfony.com/contributors", "role": "Contributors" }, { @@ -3095,6 +3638,10 @@ "keywords": [ "templating" ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/1.x" + }, "install-path": "../twig/twig" } ], diff --git a/lib/composer/installed.php b/lib/composer/installed.php index 1e691e0f2..8a2920c04 100644 --- a/lib/composer/installed.php +++ b/lib/composer/installed.php @@ -5,7 +5,7 @@ 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => '9ad341f73a2aa0bd50515d88e1daac99b124238f', + 'reference' => '73b0ed47a8fc8460fb36ada4f490d84e56ff130b', 'name' => '__root__', 'dev' => true, ), @@ -16,25 +16,43 @@ 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => '9ad341f73a2aa0bd50515d88e1daac99b124238f', + 'reference' => '73b0ed47a8fc8460fb36ada4f490d84e56ff130b', 'dev_requirement' => false, ), 'combodo/tcpdf' => array( - 'pretty_version' => '6.3.5', - 'version' => '6.3.5.0', + 'pretty_version' => '6.4.4', + 'version' => '6.4.4.0', 'type' => 'library', 'install_path' => __DIR__ . '/../combodo/tcpdf', 'aliases' => array(), - 'reference' => 'aedd4b7b8cf7fcc24e617c405c9d3304150f4b94', + 'reference' => '0e31c013ccd000aa6762e9186778aa6e259ac8e8', + 'dev_requirement' => false, + ), + 'doctrine/lexer' => array( + 'pretty_version' => '1.2.3', + 'version' => '1.2.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../doctrine/lexer', + 'aliases' => array(), + 'reference' => 'c268e882d4dbdd85e36e4ad69e02dc284f89d229', + 'dev_requirement' => false, + ), + 'egulias/email-validator' => array( + 'pretty_version' => '2.1.25', + 'version' => '2.1.25.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../egulias/email-validator', + 'aliases' => array(), + 'reference' => '0dbf5d78455d4d6a41d186da50adc1122ec066f4', 'dev_requirement' => false, ), 'nikic/php-parser' => array( - 'pretty_version' => 'v4.12.0', - 'version' => '4.12.0.0', + 'pretty_version' => 'v4.13.2', + 'version' => '4.13.2.0', 'type' => 'library', 'install_path' => __DIR__ . '/../nikic/php-parser', 'aliases' => array(), - 'reference' => '6608f01670c3cc5079e18c1dab1104e002579143', + 'reference' => '210577fe3cf7badcc5814d99455df46564f3c077', 'dev_requirement' => false, ), 'paragonie/random_compat' => array( @@ -158,21 +176,21 @@ ), ), 'scssphp/scssphp' => array( - 'pretty_version' => '1.0.6', - 'version' => '1.0.6.0', + 'pretty_version' => 'v1.10.2', + 'version' => '1.10.2.0', 'type' => 'library', 'install_path' => __DIR__ . '/../scssphp/scssphp', 'aliases' => array(), - 'reference' => '5b3c9d704950d8f9637f5110c36c281ec47dc13c', + 'reference' => '387f4f4abf5d99f16be16314c5ab856f81c82f46', 'dev_requirement' => false, ), 'swiftmailer/swiftmailer' => array( - 'pretty_version' => 'v5.4.12', - 'version' => '5.4.12.0', + 'pretty_version' => 'v6.3.0', + 'version' => '6.3.0.0', 'type' => 'library', 'install_path' => __DIR__ . '/../swiftmailer/swiftmailer', 'aliases' => array(), - 'reference' => '181b89f18a90f8925ef805f950d47a7190e9b950', + 'reference' => '8a5d5072dca8f48460fce2f4131fcc495eec654c', 'dev_requirement' => false, ), 'symfony/cache' => array( @@ -319,6 +337,33 @@ 'reference' => 'aed596913b70fae57be53d86faa2e9ef85a2297b', 'dev_requirement' => false, ), + 'symfony/polyfill-iconv' => array( + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-iconv', + 'aliases' => array(), + 'reference' => 'f1aed619e28cb077fc83fac8c4c0383578356e40', + 'dev_requirement' => false, + ), + 'symfony/polyfill-intl-idn' => array( + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn', + 'aliases' => array(), + 'reference' => '749045c69efb97c70d25d7463abba812e91f3a44', + 'dev_requirement' => false, + ), + 'symfony/polyfill-intl-normalizer' => array( + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', + 'aliases' => array(), + 'reference' => '8590a5f561694770bdcd3f9b5c69dde6945028e8', + 'dev_requirement' => false, + ), 'symfony/polyfill-mbstring' => array( 'pretty_version' => 'v1.19.0', 'version' => '1.19.0.0', @@ -346,6 +391,15 @@ 'reference' => '3fe414077251a81a1b15b1c709faf5c2fbae3d4e', 'dev_requirement' => false, ), + 'symfony/polyfill-php72' => array( + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php72', + 'aliases' => array(), + 'reference' => '9a142215a36a3888e30d0a9eeea9766764e96976', + 'dev_requirement' => false, + ), 'symfony/polyfill-util' => array( 'pretty_version' => 'v1.19.0', 'version' => '1.19.0.0', @@ -421,16 +475,16 @@ 'tecnickcom/tcpdf' => array( 'dev_requirement' => false, 'replaced' => array( - 0 => '6.3.5', + 0 => '6.4.4', ), ), 'twig/twig' => array( - 'pretty_version' => 'v1.42.4', - 'version' => '1.42.4.0', + 'pretty_version' => 'v1.42.5', + 'version' => '1.42.5.0', 'type' => 'library', 'install_path' => __DIR__ . '/../twig/twig', 'aliases' => array(), - 'reference' => 'e587180584c3d2d6cb864a0454e777bb6dcb6152', + 'reference' => '87b2ea9d8f6fd014d0621ca089bb1b3769ea3f8e', 'dev_requirement' => false, ), ), diff --git a/lib/composer/platform_check.php b/lib/composer/platform_check.php index 861c725e0..f34cfad2e 100644 --- a/lib/composer/platform_check.php +++ b/lib/composer/platform_check.php @@ -12,7 +12,6 @@ $missingExtensions = array(); extension_loaded('ctype') || $missingExtensions[] = 'ctype'; extension_loaded('dom') || $missingExtensions[] = 'dom'; extension_loaded('gd') || $missingExtensions[] = 'gd'; -extension_loaded('iconv') || $missingExtensions[] = 'iconv'; extension_loaded('json') || $missingExtensions[] = 'json'; extension_loaded('libxml') || $missingExtensions[] = 'libxml'; extension_loaded('mysqli') || $missingExtensions[] = 'mysqli'; diff --git a/lib/doctrine/lexer/LICENSE b/lib/doctrine/lexer/LICENSE new file mode 100644 index 000000000..e8fdec4af --- /dev/null +++ b/lib/doctrine/lexer/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2018 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/lib/doctrine/lexer/README.md b/lib/doctrine/lexer/README.md new file mode 100644 index 000000000..784f2a271 --- /dev/null +++ b/lib/doctrine/lexer/README.md @@ -0,0 +1,9 @@ +# Doctrine Lexer + +[![Build Status](https://github.com/doctrine/lexer/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/lexer/actions) + +Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers. + +This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL). + +https://www.doctrine-project.org/projects/lexer.html diff --git a/lib/doctrine/lexer/composer.json b/lib/doctrine/lexer/composer.json new file mode 100644 index 000000000..c43564772 --- /dev/null +++ b/lib/doctrine/lexer/composer.json @@ -0,0 +1,41 @@ +{ + "name": "doctrine/lexer", + "type": "library", + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "keywords": [ + "php", + "parser", + "lexer", + "annotations", + "docblock" + ], + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} + ], + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.11" + }, + "autoload": { + "psr-4": { "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" } + }, + "autoload-dev": { + "psr-4": { "Doctrine\\Tests\\": "tests/Doctrine" } + }, + "config": { + "allow-plugins": { + "composer/package-versions-deprecated": true, + "dealerdirect/phpcodesniffer-composer-installer": true + }, + "sort-packages": true + } +} diff --git a/lib/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php b/lib/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php new file mode 100644 index 000000000..7e8a11d44 --- /dev/null +++ b/lib/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php @@ -0,0 +1,337 @@ + + */ + private $tokens = []; + + /** + * Current lexer position in input string. + * + * @var int + */ + private $position = 0; + + /** + * Current peek of current lexer position. + * + * @var int + */ + private $peek = 0; + + /** + * The next token in the input. + * + * @var mixed[]|null + * @psalm-var Token|null + */ + public $lookahead; + + /** + * The last matched/seen token. + * + * @var mixed[]|null + * @psalm-var Token|null + */ + public $token; + + /** + * Composed regex for input parsing. + * + * @var string|null + */ + private $regex; + + /** + * Sets the input data to be tokenized. + * + * The Lexer is immediately reset and the new input tokenized. + * Any unprocessed tokens from any previous input are lost. + * + * @param string $input The input to be tokenized. + * + * @return void + */ + public function setInput($input) + { + $this->input = $input; + $this->tokens = []; + + $this->reset(); + $this->scan($input); + } + + /** + * Resets the lexer. + * + * @return void + */ + public function reset() + { + $this->lookahead = null; + $this->token = null; + $this->peek = 0; + $this->position = 0; + } + + /** + * Resets the peek pointer to 0. + * + * @return void + */ + public function resetPeek() + { + $this->peek = 0; + } + + /** + * Resets the lexer position on the input to the given position. + * + * @param int $position Position to place the lexical scanner. + * + * @return void + */ + public function resetPosition($position = 0) + { + $this->position = $position; + } + + /** + * Retrieve the original lexer's input until a given position. + * + * @param int $position + * + * @return string + */ + public function getInputUntilPosition($position) + { + return substr($this->input, 0, $position); + } + + /** + * Checks whether a given token matches the current lookahead. + * + * @param int|string $type + * + * @return bool + */ + public function isNextToken($type) + { + return $this->lookahead !== null && $this->lookahead['type'] === $type; + } + + /** + * Checks whether any of the given tokens matches the current lookahead. + * + * @param list $types + * + * @return bool + */ + public function isNextTokenAny(array $types) + { + return $this->lookahead !== null && in_array($this->lookahead['type'], $types, true); + } + + /** + * Moves to the next token in the input string. + * + * @return bool + */ + public function moveNext() + { + $this->peek = 0; + $this->token = $this->lookahead; + $this->lookahead = isset($this->tokens[$this->position]) + ? $this->tokens[$this->position++] : null; + + return $this->lookahead !== null; + } + + /** + * Tells the lexer to skip input tokens until it sees a token with the given value. + * + * @param string $type The token type to skip until. + * + * @return void + */ + public function skipUntil($type) + { + while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { + $this->moveNext(); + } + } + + /** + * Checks if given value is identical to the given token. + * + * @param mixed $value + * @param int|string $token + * + * @return bool + */ + public function isA($value, $token) + { + return $this->getType($value) === $token; + } + + /** + * Moves the lookahead token forward. + * + * @return mixed[]|null The next token or NULL if there are no more tokens ahead. + * @psalm-return Token|null + */ + public function peek() + { + if (isset($this->tokens[$this->position + $this->peek])) { + return $this->tokens[$this->position + $this->peek++]; + } + + return null; + } + + /** + * Peeks at the next token, returns it and immediately resets the peek. + * + * @return mixed[]|null The next token or NULL if there are no more tokens ahead. + * @psalm-return Token|null + */ + public function glimpse() + { + $peek = $this->peek(); + $this->peek = 0; + + return $peek; + } + + /** + * Scans the input string for tokens. + * + * @param string $input A query string. + * + * @return void + */ + protected function scan($input) + { + if (! isset($this->regex)) { + $this->regex = sprintf( + '/(%s)|%s/%s', + implode(')|(', $this->getCatchablePatterns()), + implode('|', $this->getNonCatchablePatterns()), + $this->getModifiers() + ); + } + + $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; + $matches = preg_split($this->regex, $input, -1, $flags); + + if ($matches === false) { + // Work around https://bugs.php.net/78122 + $matches = [[$input, 0]]; + } + + foreach ($matches as $match) { + // Must remain before 'value' assignment since it can change content + $type = $this->getType($match[0]); + + $this->tokens[] = [ + 'value' => $match[0], + 'type' => $type, + 'position' => $match[1], + ]; + } + } + + /** + * Gets the literal for a given token. + * + * @param int|string $token + * + * @return int|string + */ + public function getLiteral($token) + { + $className = static::class; + $reflClass = new ReflectionClass($className); + $constants = $reflClass->getConstants(); + + foreach ($constants as $name => $value) { + if ($value === $token) { + return $className . '::' . $name; + } + } + + return $token; + } + + /** + * Regex modifiers + * + * @return string + */ + protected function getModifiers() + { + return 'iu'; + } + + /** + * Lexical catchable patterns. + * + * @return string[] + */ + abstract protected function getCatchablePatterns(); + + /** + * Lexical non-catchable patterns. + * + * @return string[] + */ + abstract protected function getNonCatchablePatterns(); + + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * + * @return int|string|null + */ + abstract protected function getType(&$value); +} diff --git a/lib/doctrine/lexer/psalm.xml b/lib/doctrine/lexer/psalm.xml new file mode 100644 index 000000000..f331e50c1 --- /dev/null +++ b/lib/doctrine/lexer/psalm.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/lib/egulias/email-validator/LICENSE b/lib/egulias/email-validator/LICENSE new file mode 100644 index 000000000..c34d2c197 --- /dev/null +++ b/lib/egulias/email-validator/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2013-2016 Eduardo Gulias Davis + +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/lib/egulias/email-validator/composer.json b/lib/egulias/email-validator/composer.json new file mode 100644 index 000000000..a275696ab --- /dev/null +++ b/lib/egulias/email-validator/composer.json @@ -0,0 +1,38 @@ +{ + "name": "egulias/email-validator", + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": ["email", "validation", "validator", "emailvalidation", "emailvalidator"], + "license": "MIT", + "authors": [ + {"name": "Eduardo Gulias Davis"} + ], + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "require": { + "php": ">=5.5", + "doctrine/lexer": "^1.0.1", + "symfony/polyfill-intl-idn": "^1.10" + }, + "require-dev": { + "dominicsayers/isemail": "^3.0.7", + "phpunit/phpunit": "^4.8.36|^7.5.15", + "satooshi/php-coveralls": "^1.0.1" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Egulias\\EmailValidator\\Tests\\": "tests" + } + } +} diff --git a/lib/egulias/email-validator/src/EmailLexer.php b/lib/egulias/email-validator/src/EmailLexer.php new file mode 100644 index 000000000..59dcd5876 --- /dev/null +++ b/lib/egulias/email-validator/src/EmailLexer.php @@ -0,0 +1,283 @@ + self::S_OPENPARENTHESIS, + ')' => self::S_CLOSEPARENTHESIS, + '<' => self::S_LOWERTHAN, + '>' => self::S_GREATERTHAN, + '[' => self::S_OPENBRACKET, + ']' => self::S_CLOSEBRACKET, + ':' => self::S_COLON, + ';' => self::S_SEMICOLON, + '@' => self::S_AT, + '\\' => self::S_BACKSLASH, + '/' => self::S_SLASH, + ',' => self::S_COMMA, + '.' => self::S_DOT, + "'" => self::S_SQUOTE, + "`" => self::S_BACKTICK, + '"' => self::S_DQUOTE, + '-' => self::S_HYPHEN, + '::' => self::S_DOUBLECOLON, + ' ' => self::S_SP, + "\t" => self::S_HTAB, + "\r" => self::S_CR, + "\n" => self::S_LF, + "\r\n" => self::CRLF, + 'IPv6' => self::S_IPV6TAG, + '{' => self::S_OPENQBRACKET, + '}' => self::S_CLOSEQBRACKET, + '' => self::S_EMPTY, + '\0' => self::C_NUL, + ); + + /** + * @var bool + */ + protected $hasInvalidTokens = false; + + /** + * @var array + * + * @psalm-var array{value:string, type:null|int, position:int}|array + */ + protected $previous = []; + + /** + * The last matched/seen token. + * + * @var array + * + * @psalm-var array{value:string, type:null|int, position:int} + */ + public $token; + + /** + * The next token in the input. + * + * @var array|null + */ + public $lookahead; + + /** + * @psalm-var array{value:'', type:null, position:0} + */ + private static $nullToken = [ + 'value' => '', + 'type' => null, + 'position' => 0, + ]; + + public function __construct() + { + $this->previous = $this->token = self::$nullToken; + $this->lookahead = null; + } + + /** + * @return void + */ + public function reset() + { + $this->hasInvalidTokens = false; + parent::reset(); + $this->previous = $this->token = self::$nullToken; + } + + /** + * @return bool + */ + public function hasInvalidTokens() + { + return $this->hasInvalidTokens; + } + + /** + * @param int $type + * @throws \UnexpectedValueException + * @return boolean + * + * @psalm-suppress InvalidScalarArgument + */ + public function find($type) + { + $search = clone $this; + $search->skipUntil($type); + + if (!$search->lookahead) { + throw new \UnexpectedValueException($type . ' not found'); + } + return true; + } + + /** + * getPrevious + * + * @return array + */ + public function getPrevious() + { + return $this->previous; + } + + /** + * moveNext + * + * @return boolean + */ + public function moveNext() + { + $this->previous = $this->token; + $hasNext = parent::moveNext(); + $this->token = $this->token ?: self::$nullToken; + + return $hasNext; + } + + /** + * Lexical catchable patterns. + * + * @return string[] + */ + protected function getCatchablePatterns() + { + return array( + '[a-zA-Z_]+[46]?', //ASCII and domain literal + '[^\x00-\x7F]', //UTF-8 + '[0-9]+', + '\r\n', + '::', + '\s+?', + '.', + ); + } + + /** + * Lexical non-catchable patterns. + * + * @return string[] + */ + protected function getNonCatchablePatterns() + { + return array('[\xA0-\xff]+'); + } + + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * @throws \InvalidArgumentException + * @return integer + */ + protected function getType(&$value) + { + if ($this->isNullType($value)) { + return self::C_NUL; + } + + if ($this->isValid($value)) { + return $this->charValue[$value]; + } + + if ($this->isUTF8Invalid($value)) { + $this->hasInvalidTokens = true; + return self::INVALID; + } + + return self::GENERIC; + } + + /** + * @param string $value + * + * @return bool + */ + protected function isValid($value) + { + if (isset($this->charValue[$value])) { + return true; + } + + return false; + } + + /** + * @param string $value + * @return bool + */ + protected function isNullType($value) + { + if ($value === "\0") { + return true; + } + + return false; + } + + /** + * @param string $value + * @return bool + */ + protected function isUTF8Invalid($value) + { + if (preg_match('/\p{Cc}+/u', $value)) { + return true; + } + + return false; + } + + /** + * @return string + */ + protected function getModifiers() + { + return 'iu'; + } +} diff --git a/lib/egulias/email-validator/src/EmailParser.php b/lib/egulias/email-validator/src/EmailParser.php new file mode 100644 index 000000000..6b7bad669 --- /dev/null +++ b/lib/egulias/email-validator/src/EmailParser.php @@ -0,0 +1,137 @@ + + */ +class EmailParser +{ + const EMAIL_MAX_LENGTH = 254; + + /** + * @var array + */ + protected $warnings = []; + + /** + * @var string + */ + protected $domainPart = ''; + + /** + * @var string + */ + protected $localPart = ''; + /** + * @var EmailLexer + */ + protected $lexer; + + /** + * @var LocalPart + */ + protected $localPartParser; + + /** + * @var DomainPart + */ + protected $domainPartParser; + + public function __construct(EmailLexer $lexer) + { + $this->lexer = $lexer; + $this->localPartParser = new LocalPart($this->lexer); + $this->domainPartParser = new DomainPart($this->lexer); + } + + /** + * @param string $str + * @return array + */ + public function parse($str) + { + $this->lexer->setInput($str); + + if (!$this->hasAtToken()) { + throw new NoLocalPart(); + } + + + $this->localPartParser->parse($str); + $this->domainPartParser->parse($str); + + $this->setParts($str); + + if ($this->lexer->hasInvalidTokens()) { + throw new ExpectingATEXT(); + } + + return array('local' => $this->localPart, 'domain' => $this->domainPart); + } + + /** + * @return Warning\Warning[] + */ + public function getWarnings() + { + $localPartWarnings = $this->localPartParser->getWarnings(); + $domainPartWarnings = $this->domainPartParser->getWarnings(); + $this->warnings = array_merge($localPartWarnings, $domainPartWarnings); + + $this->addLongEmailWarning($this->localPart, $this->domainPart); + + return $this->warnings; + } + + /** + * @return string + */ + public function getParsedDomainPart() + { + return $this->domainPart; + } + + /** + * @param string $email + */ + protected function setParts($email) + { + $parts = explode('@', $email); + $this->domainPart = $this->domainPartParser->getDomainPart(); + $this->localPart = $parts[0]; + } + + /** + * @return bool + */ + protected function hasAtToken() + { + $this->lexer->moveNext(); + $this->lexer->moveNext(); + if ($this->lexer->token['type'] === EmailLexer::S_AT) { + return false; + } + + return true; + } + + /** + * @param string $localPart + * @param string $parsedDomainPart + */ + protected function addLongEmailWarning($localPart, $parsedDomainPart) + { + if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) { + $this->warnings[EmailTooLong::CODE] = new EmailTooLong(); + } + } +} diff --git a/lib/egulias/email-validator/src/EmailValidator.php b/lib/egulias/email-validator/src/EmailValidator.php new file mode 100644 index 000000000..a30f21dcd --- /dev/null +++ b/lib/egulias/email-validator/src/EmailValidator.php @@ -0,0 +1,67 @@ +lexer = new EmailLexer(); + } + + /** + * @param string $email + * @param EmailValidation $emailValidation + * @return bool + */ + public function isValid($email, EmailValidation $emailValidation) + { + $isValid = $emailValidation->isValid($email, $this->lexer); + $this->warnings = $emailValidation->getWarnings(); + $this->error = $emailValidation->getError(); + + return $isValid; + } + + /** + * @return boolean + */ + public function hasWarnings() + { + return !empty($this->warnings); + } + + /** + * @return array + */ + public function getWarnings() + { + return $this->warnings; + } + + /** + * @return InvalidEmail|null + */ + public function getError() + { + return $this->error; + } +} diff --git a/lib/egulias/email-validator/src/Exception/AtextAfterCFWS.php b/lib/egulias/email-validator/src/Exception/AtextAfterCFWS.php new file mode 100644 index 000000000..97f41a2ca --- /dev/null +++ b/lib/egulias/email-validator/src/Exception/AtextAfterCFWS.php @@ -0,0 +1,9 @@ +lexer->moveNext(); + + $this->performDomainStartChecks(); + + $domain = $this->doParseDomainPart(); + + $prev = $this->lexer->getPrevious(); + $length = strlen($domain); + + if ($prev['type'] === EmailLexer::S_DOT) { + throw new DotAtEnd(); + } + if ($prev['type'] === EmailLexer::S_HYPHEN) { + throw new DomainHyphened(); + } + if ($length > self::DOMAIN_MAX_LENGTH) { + $this->warnings[DomainTooLong::CODE] = new DomainTooLong(); + } + if ($prev['type'] === EmailLexer::S_CR) { + throw new CRLFAtTheEnd(); + } + $this->domainPart = $domain; + } + + private function performDomainStartChecks() + { + $this->checkInvalidTokensAfterAT(); + $this->checkEmptyDomain(); + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->warnings[DeprecatedComment::CODE] = new DeprecatedComment(); + $this->parseDomainComments(); + } + } + + private function checkEmptyDomain() + { + $thereIsNoDomain = $this->lexer->token['type'] === EmailLexer::S_EMPTY || + ($this->lexer->token['type'] === EmailLexer::S_SP && + !$this->lexer->isNextToken(EmailLexer::GENERIC)); + + if ($thereIsNoDomain) { + throw new NoDomainPart(); + } + } + + private function checkInvalidTokensAfterAT() + { + if ($this->lexer->token['type'] === EmailLexer::S_DOT) { + throw new DotAtStart(); + } + if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) { + throw new DomainHyphened(); + } + } + + /** + * @return string + */ + public function getDomainPart() + { + return $this->domainPart; + } + + /** + * @param string $addressLiteral + * @param int $maxGroups + */ + public function checkIPV6Tag($addressLiteral, $maxGroups = 8) + { + $prev = $this->lexer->getPrevious(); + if ($prev['type'] === EmailLexer::S_COLON) { + $this->warnings[IPV6ColonEnd::CODE] = new IPV6ColonEnd(); + } + + $IPv6 = substr($addressLiteral, 5); + //Daniel Marschall's new IPv6 testing strategy + $matchesIP = explode(':', $IPv6); + $groupCount = count($matchesIP); + $colons = strpos($IPv6, '::'); + + if (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) { + $this->warnings[IPV6BadChar::CODE] = new IPV6BadChar(); + } + + if ($colons === false) { + // We need exactly the right number of groups + if ($groupCount !== $maxGroups) { + $this->warnings[IPV6GroupCount::CODE] = new IPV6GroupCount(); + } + return; + } + + if ($colons !== strrpos($IPv6, '::')) { + $this->warnings[IPV6DoubleColon::CODE] = new IPV6DoubleColon(); + return; + } + + if ($colons === 0 || $colons === (strlen($IPv6) - 2)) { + // RFC 4291 allows :: at the start or end of an address + //with 7 other groups in addition + ++$maxGroups; + } + + if ($groupCount > $maxGroups) { + $this->warnings[IPV6MaxGroups::CODE] = new IPV6MaxGroups(); + } elseif ($groupCount === $maxGroups) { + $this->warnings[IPV6Deprecated::CODE] = new IPV6Deprecated(); + } + } + + /** + * @return string + */ + protected function doParseDomainPart() + { + $domain = ''; + $label = ''; + $openedParenthesis = 0; + do { + $prev = $this->lexer->getPrevious(); + + $this->checkNotAllowedChars($this->lexer->token); + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->parseComments(); + $openedParenthesis += $this->getOpenedParenthesis(); + $this->lexer->moveNext(); + $tmpPrev = $this->lexer->getPrevious(); + if ($tmpPrev['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + $openedParenthesis--; + } + } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + if ($openedParenthesis === 0) { + throw new UnopenedComment(); + } else { + $openedParenthesis--; + } + } + + $this->checkConsecutiveDots(); + $this->checkDomainPartExceptions($prev); + + if ($this->hasBrackets()) { + $this->parseDomainLiteral(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_DOT) { + $this->checkLabelLength($label); + $label = ''; + } else { + $label .= $this->lexer->token['value']; + } + + if ($this->isFWS()) { + $this->parseFWS(); + } + + $domain .= $this->lexer->token['value']; + $this->lexer->moveNext(); + if ($this->lexer->token['type'] === EmailLexer::S_SP) { + throw new CharNotAllowed(); + } + } while (null !== $this->lexer->token['type']); + + $this->checkLabelLength($label); + + return $domain; + } + + private function checkNotAllowedChars(array $token) + { + $notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true]; + if (isset($notAllowed[$token['type']])) { + throw new CharNotAllowed(); + } + } + + /** + * @return string|false + */ + protected function parseDomainLiteral() + { + if ($this->lexer->isNextToken(EmailLexer::S_COLON)) { + $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); + } + if ($this->lexer->isNextToken(EmailLexer::S_IPV6TAG)) { + $lexer = clone $this->lexer; + $lexer->moveNext(); + if ($lexer->isNextToken(EmailLexer::S_DOUBLECOLON)) { + $this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart(); + } + } + + return $this->doParseDomainLiteral(); + } + + /** + * @return string|false + */ + protected function doParseDomainLiteral() + { + $IPv6TAG = false; + $addressLiteral = ''; + do { + if ($this->lexer->token['type'] === EmailLexer::C_NUL) { + throw new ExpectingDTEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::INVALID || + $this->lexer->token['type'] === EmailLexer::C_DEL || + $this->lexer->token['type'] === EmailLexer::S_LF + ) { + $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); + } + + if ($this->lexer->isNextTokenAny(array(EmailLexer::S_OPENQBRACKET, EmailLexer::S_OPENBRACKET))) { + throw new ExpectingDTEXT(); + } + + if ($this->lexer->isNextTokenAny( + array(EmailLexer::S_HTAB, EmailLexer::S_SP, $this->lexer->token['type'] === EmailLexer::CRLF) + )) { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + $this->parseFWS(); + } + + if ($this->lexer->isNextToken(EmailLexer::S_CR)) { + throw new CRNoLF(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) { + $this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT(); + $addressLiteral .= $this->lexer->token['value']; + $this->lexer->moveNext(); + $this->validateQuotedPair(); + } + if ($this->lexer->token['type'] === EmailLexer::S_IPV6TAG) { + $IPv6TAG = true; + } + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEQBRACKET) { + break; + } + + $addressLiteral .= $this->lexer->token['value']; + + } while ($this->lexer->moveNext()); + + $addressLiteral = str_replace('[', '', $addressLiteral); + $addressLiteral = $this->checkIPV4Tag($addressLiteral); + + if (false === $addressLiteral) { + return $addressLiteral; + } + + if (!$IPv6TAG) { + $this->warnings[DomainLiteral::CODE] = new DomainLiteral(); + return $addressLiteral; + } + + $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); + + $this->checkIPV6Tag($addressLiteral); + + return $addressLiteral; + } + + /** + * @param string $addressLiteral + * + * @return string|false + */ + protected function checkIPV4Tag($addressLiteral) + { + $matchesIP = array(); + + // Extract IPv4 part from the end of the address-literal (if there is one) + if (preg_match( + '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', + $addressLiteral, + $matchesIP + ) > 0 + ) { + $index = strrpos($addressLiteral, $matchesIP[0]); + if ($index === 0) { + $this->warnings[AddressLiteral::CODE] = new AddressLiteral(); + return false; + } + // Convert IPv4 part to IPv6 format for further testing + $addressLiteral = substr($addressLiteral, 0, (int) $index) . '0:0'; + } + + return $addressLiteral; + } + + protected function checkDomainPartExceptions(array $prev) + { + $invalidDomainTokens = array( + EmailLexer::S_DQUOTE => true, + EmailLexer::S_SQUOTE => true, + EmailLexer::S_BACKTICK => true, + EmailLexer::S_SEMICOLON => true, + EmailLexer::S_GREATERTHAN => true, + EmailLexer::S_LOWERTHAN => true, + ); + + if (isset($invalidDomainTokens[$this->lexer->token['type']])) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_COMMA) { + throw new CommaInDomain(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_AT) { + throw new ConsecutiveAt(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_OPENQBRACKET && $prev['type'] !== EmailLexer::S_AT) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN && $this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new DomainHyphened(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH + && $this->lexer->isNextToken(EmailLexer::GENERIC)) { + throw new ExpectingATEXT(); + } + } + + /** + * @return bool + */ + protected function hasBrackets() + { + if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) { + return false; + } + + try { + $this->lexer->find(EmailLexer::S_CLOSEBRACKET); + } catch (\RuntimeException $e) { + throw new ExpectingDomainLiteralClose(); + } + + return true; + } + + /** + * @param string $label + */ + protected function checkLabelLength($label) + { + if ($this->isLabelTooLong($label)) { + $this->warnings[LabelTooLong::CODE] = new LabelTooLong(); + } + } + + /** + * @param string $label + * @return bool + */ + private function isLabelTooLong($label) + { + if (preg_match('/[^\x00-\x7F]/', $label)) { + idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo); + + return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG); + } + + return strlen($label) > self::LABEL_MAX_LENGTH; + } + + protected function parseDomainComments() + { + $this->isUnclosedComment(); + while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { + $this->warnEscaping(); + $this->lexer->moveNext(); + } + + $this->lexer->moveNext(); + if ($this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new ExpectingATEXT(); + } + } + + protected function addTLDWarnings() + { + if ($this->warnings[DomainLiteral::CODE]) { + $this->warnings[TLD::CODE] = new TLD(); + } + } +} diff --git a/lib/egulias/email-validator/src/Parser/LocalPart.php b/lib/egulias/email-validator/src/Parser/LocalPart.php new file mode 100644 index 000000000..3c21f34ac --- /dev/null +++ b/lib/egulias/email-validator/src/Parser/LocalPart.php @@ -0,0 +1,145 @@ +lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) { + if ($this->lexer->token['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type']) { + throw new DotAtStart(); + } + + $closingQuote = $this->checkDQUOTE($closingQuote); + if ($closingQuote && $parseDQuote) { + $parseDQuote = $this->parseDoubleQuote(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) { + $this->parseComments(); + $openedParenthesis += $this->getOpenedParenthesis(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) { + if ($openedParenthesis === 0) { + throw new UnopenedComment(); + } + + $openedParenthesis--; + } + + $this->checkConsecutiveDots(); + + if ($this->lexer->token['type'] === EmailLexer::S_DOT && + $this->lexer->isNextToken(EmailLexer::S_AT) + ) { + throw new DotAtEnd(); + } + + $this->warnEscaping(); + $this->isInvalidToken($this->lexer->token, $closingQuote); + + if ($this->isFWS()) { + $this->parseFWS(); + } + + $totalLength += strlen($this->lexer->token['value']); + $this->lexer->moveNext(); + } + + if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) { + $this->warnings[LocalTooLong::CODE] = new LocalTooLong(); + } + } + + /** + * @return bool + */ + protected function parseDoubleQuote() + { + $parseAgain = true; + $special = array( + EmailLexer::S_CR => true, + EmailLexer::S_HTAB => true, + EmailLexer::S_LF => true + ); + + $invalid = array( + EmailLexer::C_NUL => true, + EmailLexer::S_HTAB => true, + EmailLexer::S_CR => true, + EmailLexer::S_LF => true + ); + $setSpecialsWarning = true; + + $this->lexer->moveNext(); + + while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && null !== $this->lexer->token['type']) { + $parseAgain = false; + if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + $setSpecialsWarning = false; + } + if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH && $this->lexer->isNextToken(EmailLexer::S_DQUOTE)) { + $this->lexer->moveNext(); + } + + $this->lexer->moveNext(); + + if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) { + throw new ExpectingATEXT(); + } + } + + $prev = $this->lexer->getPrevious(); + + if ($prev['type'] === EmailLexer::S_BACKSLASH) { + if (!$this->checkDQUOTE(false)) { + throw new UnclosedQuotedString(); + } + } + + if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) { + throw new ExpectingAT(); + } + + return $parseAgain; + } + + /** + * @param bool $closingQuote + */ + protected function isInvalidToken(array $token, $closingQuote) + { + $forbidden = array( + EmailLexer::S_COMMA, + EmailLexer::S_CLOSEBRACKET, + EmailLexer::S_OPENBRACKET, + EmailLexer::S_GREATERTHAN, + EmailLexer::S_LOWERTHAN, + EmailLexer::S_COLON, + EmailLexer::S_SEMICOLON, + EmailLexer::INVALID + ); + + if (in_array($token['type'], $forbidden) && !$closingQuote) { + throw new ExpectingATEXT(); + } + } +} diff --git a/lib/egulias/email-validator/src/Parser/Parser.php b/lib/egulias/email-validator/src/Parser/Parser.php new file mode 100644 index 000000000..ccdc93889 --- /dev/null +++ b/lib/egulias/email-validator/src/Parser/Parser.php @@ -0,0 +1,249 @@ +lexer = $lexer; + } + + /** + * @return \Egulias\EmailValidator\Warning\Warning[] + */ + public function getWarnings() + { + return $this->warnings; + } + + /** + * @param string $str + */ + abstract public function parse($str); + + /** @return int */ + public function getOpenedParenthesis() + { + return $this->openedParenthesis; + } + + /** + * validateQuotedPair + */ + protected function validateQuotedPair() + { + if (!($this->lexer->token['type'] === EmailLexer::INVALID + || $this->lexer->token['type'] === EmailLexer::C_DEL)) { + throw new ExpectingQPair(); + } + + $this->warnings[QuotedPart::CODE] = + new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); + } + + protected function parseComments() + { + $this->openedParenthesis = 1; + $this->isUnclosedComment(); + $this->warnings[Comment::CODE] = new Comment(); + while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) { + if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) { + $this->openedParenthesis++; + } + $this->warnEscaping(); + $this->lexer->moveNext(); + } + + $this->lexer->moveNext(); + if ($this->lexer->isNextTokenAny(array(EmailLexer::GENERIC, EmailLexer::S_EMPTY))) { + throw new ExpectingATEXT(); + } + + if ($this->lexer->isNextToken(EmailLexer::S_AT)) { + $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); + } + } + + /** + * @return bool + */ + protected function isUnclosedComment() + { + try { + $this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS); + return true; + } catch (\RuntimeException $e) { + throw new UnclosedComment(); + } + } + + protected function parseFWS() + { + $previous = $this->lexer->getPrevious(); + + $this->checkCRLFInFWS(); + + if ($this->lexer->token['type'] === EmailLexer::S_CR) { + throw new CRNoLF(); + } + + if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) { + throw new AtextAfterCFWS(); + } + + if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) { + throw new ExpectingCTEXT(); + } + + if ($this->lexer->isNextToken(EmailLexer::S_AT) || $previous['type'] === EmailLexer::S_AT) { + $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt(); + } else { + $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS(); + } + } + + protected function checkConsecutiveDots() + { + if ($this->lexer->token['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) { + throw new ConsecutiveDot(); + } + } + + /** + * @return bool + */ + protected function isFWS() + { + if ($this->escaped()) { + return false; + } + + if ($this->lexer->token['type'] === EmailLexer::S_SP || + $this->lexer->token['type'] === EmailLexer::S_HTAB || + $this->lexer->token['type'] === EmailLexer::S_CR || + $this->lexer->token['type'] === EmailLexer::S_LF || + $this->lexer->token['type'] === EmailLexer::CRLF + ) { + return true; + } + + return false; + } + + /** + * @return bool + */ + protected function escaped() + { + $previous = $this->lexer->getPrevious(); + + if ($previous && $previous['type'] === EmailLexer::S_BACKSLASH + && + $this->lexer->token['type'] !== EmailLexer::GENERIC + ) { + return true; + } + + return false; + } + + /** + * @return bool + */ + protected function warnEscaping() + { + if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) { + return false; + } + + if ($this->lexer->isNextToken(EmailLexer::GENERIC)) { + throw new ExpectingATEXT(); + } + + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) { + return false; + } + + $this->warnings[QuotedPart::CODE] = + new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']); + return true; + + } + + /** + * @param bool $hasClosingQuote + * + * @return bool + */ + protected function checkDQUOTE($hasClosingQuote) + { + if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) { + return $hasClosingQuote; + } + if ($hasClosingQuote) { + return $hasClosingQuote; + } + $previous = $this->lexer->getPrevious(); + if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) { + throw new ExpectingATEXT(); + } + + try { + $this->lexer->find(EmailLexer::S_DQUOTE); + $hasClosingQuote = true; + } catch (\Exception $e) { + throw new UnclosedQuotedString(); + } + $this->warnings[QuotedString::CODE] = new QuotedString($previous['value'], $this->lexer->token['value']); + + return $hasClosingQuote; + } + + protected function checkCRLFInFWS() + { + if ($this->lexer->token['type'] !== EmailLexer::CRLF) { + return; + } + + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { + throw new CRLFX2(); + } + + if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) { + throw new CRLFAtTheEnd(); + } + } +} diff --git a/lib/egulias/email-validator/src/Validation/DNSCheckValidation.php b/lib/egulias/email-validator/src/Validation/DNSCheckValidation.php new file mode 100644 index 000000000..491082a59 --- /dev/null +++ b/lib/egulias/email-validator/src/Validation/DNSCheckValidation.php @@ -0,0 +1,166 @@ +error = new LocalOrReservedDomain(); + return false; + } + + return $this->checkDns($host); + } + + public function getError() + { + return $this->error; + } + + public function getWarnings() + { + return $this->warnings; + } + + /** + * @param string $host + * + * @return bool + */ + protected function checkDns($host) + { + $variant = INTL_IDNA_VARIANT_UTS46; + + $host = rtrim(idn_to_ascii($host, IDNA_DEFAULT, $variant), '.') . '.'; + + return $this->validateDnsRecords($host); + } + + + /** + * Validate the DNS records for given host. + * + * @param string $host A set of DNS records in the format returned by dns_get_record. + * + * @return bool True on success. + */ + private function validateDnsRecords($host) + { + // Get all MX, A and AAAA DNS records for host + // Using @ as workaround to fix https://bugs.php.net/bug.php?id=73149 + $dnsRecords = @dns_get_record($host, DNS_MX + DNS_A + DNS_AAAA); + + + // No MX, A or AAAA DNS records + if (empty($dnsRecords)) { + $this->error = new NoDNSRecord(); + return false; + } + + // For each DNS record + foreach ($dnsRecords as $dnsRecord) { + if (!$this->validateMXRecord($dnsRecord)) { + return false; + } + } + + // No MX records (fallback to A or AAAA records) + if (empty($this->mxRecords)) { + $this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord(); + } + + return true; + } + + /** + * Validate an MX record + * + * @param array $dnsRecord Given DNS record. + * + * @return bool True if valid. + */ + private function validateMxRecord($dnsRecord) + { + if ($dnsRecord['type'] !== 'MX') { + return true; + } + + // "Null MX" record indicates the domain accepts no mail (https://tools.ietf.org/html/rfc7505) + if (empty($dnsRecord['target']) || $dnsRecord['target'] === '.') { + $this->error = new DomainAcceptsNoMail(); + return false; + } + + $this->mxRecords[] = $dnsRecord; + + return true; + } +} diff --git a/lib/egulias/email-validator/src/Validation/EmailValidation.php b/lib/egulias/email-validator/src/Validation/EmailValidation.php new file mode 100644 index 000000000..d5a015be5 --- /dev/null +++ b/lib/egulias/email-validator/src/Validation/EmailValidation.php @@ -0,0 +1,34 @@ +errors = $errors; + parent::__construct(); + } + + /** + * @return InvalidEmail[] + */ + public function getErrors() + { + return $this->errors; + } +} diff --git a/lib/egulias/email-validator/src/Validation/MultipleValidationWithAnd.php b/lib/egulias/email-validator/src/Validation/MultipleValidationWithAnd.php new file mode 100644 index 000000000..feb224023 --- /dev/null +++ b/lib/egulias/email-validator/src/Validation/MultipleValidationWithAnd.php @@ -0,0 +1,124 @@ +validations = $validations; + $this->mode = $mode; + } + + /** + * {@inheritdoc} + */ + public function isValid($email, EmailLexer $emailLexer) + { + $result = true; + $errors = []; + foreach ($this->validations as $validation) { + $emailLexer->reset(); + $validationResult = $validation->isValid($email, $emailLexer); + $result = $result && $validationResult; + $this->warnings = array_merge($this->warnings, $validation->getWarnings()); + $errors = $this->addNewError($validation->getError(), $errors); + + if ($this->shouldStop($result)) { + break; + } + } + + if (!empty($errors)) { + $this->error = new MultipleErrors($errors); + } + + return $result; + } + + /** + * @param \Egulias\EmailValidator\Exception\InvalidEmail|null $possibleError + * @param \Egulias\EmailValidator\Exception\InvalidEmail[] $errors + * + * @return \Egulias\EmailValidator\Exception\InvalidEmail[] + */ + private function addNewError($possibleError, array $errors) + { + if (null !== $possibleError) { + $errors[] = $possibleError; + } + + return $errors; + } + + /** + * @param bool $result + * + * @return bool + */ + private function shouldStop($result) + { + return !$result && $this->mode === self::STOP_ON_ERROR; + } + + /** + * Returns the validation errors. + * + * @return MultipleErrors|null + */ + public function getError() + { + return $this->error; + } + + /** + * {@inheritdoc} + */ + public function getWarnings() + { + return $this->warnings; + } +} diff --git a/lib/egulias/email-validator/src/Validation/NoRFCWarningsValidation.php b/lib/egulias/email-validator/src/Validation/NoRFCWarningsValidation.php new file mode 100644 index 000000000..6b31e5440 --- /dev/null +++ b/lib/egulias/email-validator/src/Validation/NoRFCWarningsValidation.php @@ -0,0 +1,41 @@ +getWarnings())) { + return true; + } + + $this->error = new RFCWarnings(); + + return false; + } + + /** + * {@inheritdoc} + */ + public function getError() + { + return $this->error ?: parent::getError(); + } +} diff --git a/lib/egulias/email-validator/src/Validation/RFCValidation.php b/lib/egulias/email-validator/src/Validation/RFCValidation.php new file mode 100644 index 000000000..8781e0b62 --- /dev/null +++ b/lib/egulias/email-validator/src/Validation/RFCValidation.php @@ -0,0 +1,49 @@ +parser = new EmailParser($emailLexer); + try { + $this->parser->parse((string)$email); + } catch (InvalidEmail $invalid) { + $this->error = $invalid; + return false; + } + + $this->warnings = $this->parser->getWarnings(); + return true; + } + + public function getError() + { + return $this->error; + } + + public function getWarnings() + { + return $this->warnings; + } +} diff --git a/lib/egulias/email-validator/src/Validation/SpoofCheckValidation.php b/lib/egulias/email-validator/src/Validation/SpoofCheckValidation.php new file mode 100644 index 000000000..e10bfabd9 --- /dev/null +++ b/lib/egulias/email-validator/src/Validation/SpoofCheckValidation.php @@ -0,0 +1,51 @@ +setChecks(Spoofchecker::SINGLE_SCRIPT); + + if ($checker->isSuspicious($email)) { + $this->error = new SpoofEmail(); + } + + return $this->error === null; + } + + /** + * @return InvalidEmail|null + */ + public function getError() + { + return $this->error; + } + + public function getWarnings() + { + return []; + } +} diff --git a/lib/egulias/email-validator/src/Warning/AddressLiteral.php b/lib/egulias/email-validator/src/Warning/AddressLiteral.php new file mode 100644 index 000000000..77e70f7f5 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/AddressLiteral.php @@ -0,0 +1,14 @@ +message = 'Address literal in domain part'; + $this->rfcNumber = 5321; + } +} diff --git a/lib/egulias/email-validator/src/Warning/CFWSNearAt.php b/lib/egulias/email-validator/src/Warning/CFWSNearAt.php new file mode 100644 index 000000000..be43bbe6f --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/CFWSNearAt.php @@ -0,0 +1,13 @@ +message = "Deprecated folding white space near @"; + } +} diff --git a/lib/egulias/email-validator/src/Warning/CFWSWithFWS.php b/lib/egulias/email-validator/src/Warning/CFWSWithFWS.php new file mode 100644 index 000000000..dea3450ec --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/CFWSWithFWS.php @@ -0,0 +1,13 @@ +message = 'Folding whites space followed by folding white space'; + } +} diff --git a/lib/egulias/email-validator/src/Warning/Comment.php b/lib/egulias/email-validator/src/Warning/Comment.php new file mode 100644 index 000000000..704c2908b --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/Comment.php @@ -0,0 +1,13 @@ +message = "Comments found in this email"; + } +} diff --git a/lib/egulias/email-validator/src/Warning/DeprecatedComment.php b/lib/egulias/email-validator/src/Warning/DeprecatedComment.php new file mode 100644 index 000000000..ad43bd7c9 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/DeprecatedComment.php @@ -0,0 +1,13 @@ +message = 'Deprecated comments'; + } +} diff --git a/lib/egulias/email-validator/src/Warning/DomainLiteral.php b/lib/egulias/email-validator/src/Warning/DomainLiteral.php new file mode 100644 index 000000000..6f36b5e29 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/DomainLiteral.php @@ -0,0 +1,14 @@ +message = 'Domain Literal'; + $this->rfcNumber = 5322; + } +} diff --git a/lib/egulias/email-validator/src/Warning/DomainTooLong.php b/lib/egulias/email-validator/src/Warning/DomainTooLong.php new file mode 100644 index 000000000..61ff17a76 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/DomainTooLong.php @@ -0,0 +1,14 @@ +message = 'Domain is too long, exceeds 255 chars'; + $this->rfcNumber = 5322; + } +} diff --git a/lib/egulias/email-validator/src/Warning/EmailTooLong.php b/lib/egulias/email-validator/src/Warning/EmailTooLong.php new file mode 100644 index 000000000..497309dbb --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/EmailTooLong.php @@ -0,0 +1,15 @@ +message = 'Email is too long, exceeds ' . EmailParser::EMAIL_MAX_LENGTH; + } +} diff --git a/lib/egulias/email-validator/src/Warning/IPV6BadChar.php b/lib/egulias/email-validator/src/Warning/IPV6BadChar.php new file mode 100644 index 000000000..ba2fcc01b --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/IPV6BadChar.php @@ -0,0 +1,14 @@ +message = 'Bad char in IPV6 domain literal'; + $this->rfcNumber = 5322; + } +} diff --git a/lib/egulias/email-validator/src/Warning/IPV6ColonEnd.php b/lib/egulias/email-validator/src/Warning/IPV6ColonEnd.php new file mode 100644 index 000000000..41afa78c6 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/IPV6ColonEnd.php @@ -0,0 +1,14 @@ +message = ':: found at the end of the domain literal'; + $this->rfcNumber = 5322; + } +} diff --git a/lib/egulias/email-validator/src/Warning/IPV6ColonStart.php b/lib/egulias/email-validator/src/Warning/IPV6ColonStart.php new file mode 100644 index 000000000..1bf754e30 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/IPV6ColonStart.php @@ -0,0 +1,14 @@ +message = ':: found at the start of the domain literal'; + $this->rfcNumber = 5322; + } +} diff --git a/lib/egulias/email-validator/src/Warning/IPV6Deprecated.php b/lib/egulias/email-validator/src/Warning/IPV6Deprecated.php new file mode 100644 index 000000000..d752caaa1 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/IPV6Deprecated.php @@ -0,0 +1,14 @@ +message = 'Deprecated form of IPV6'; + $this->rfcNumber = 5321; + } +} diff --git a/lib/egulias/email-validator/src/Warning/IPV6DoubleColon.php b/lib/egulias/email-validator/src/Warning/IPV6DoubleColon.php new file mode 100644 index 000000000..4f8239499 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/IPV6DoubleColon.php @@ -0,0 +1,14 @@ +message = 'Double colon found after IPV6 tag'; + $this->rfcNumber = 5322; + } +} diff --git a/lib/egulias/email-validator/src/Warning/IPV6GroupCount.php b/lib/egulias/email-validator/src/Warning/IPV6GroupCount.php new file mode 100644 index 000000000..a59d317f2 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/IPV6GroupCount.php @@ -0,0 +1,14 @@ +message = 'Group count is not IPV6 valid'; + $this->rfcNumber = 5322; + } +} diff --git a/lib/egulias/email-validator/src/Warning/IPV6MaxGroups.php b/lib/egulias/email-validator/src/Warning/IPV6MaxGroups.php new file mode 100644 index 000000000..936274c13 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/IPV6MaxGroups.php @@ -0,0 +1,14 @@ +message = 'Reached the maximum number of IPV6 groups allowed'; + $this->rfcNumber = 5321; + } +} diff --git a/lib/egulias/email-validator/src/Warning/LabelTooLong.php b/lib/egulias/email-validator/src/Warning/LabelTooLong.php new file mode 100644 index 000000000..daf07f408 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/LabelTooLong.php @@ -0,0 +1,14 @@ +message = 'Label too long'; + $this->rfcNumber = 5322; + } +} diff --git a/lib/egulias/email-validator/src/Warning/LocalTooLong.php b/lib/egulias/email-validator/src/Warning/LocalTooLong.php new file mode 100644 index 000000000..0d08d8b35 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/LocalTooLong.php @@ -0,0 +1,15 @@ +message = 'Local part is too long, exceeds 64 chars (octets)'; + $this->rfcNumber = 5322; + } +} diff --git a/lib/egulias/email-validator/src/Warning/NoDNSMXRecord.php b/lib/egulias/email-validator/src/Warning/NoDNSMXRecord.php new file mode 100644 index 000000000..b3c21a1f3 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/NoDNSMXRecord.php @@ -0,0 +1,14 @@ +message = 'No MX DSN record was found for this email'; + $this->rfcNumber = 5321; + } +} diff --git a/lib/egulias/email-validator/src/Warning/ObsoleteDTEXT.php b/lib/egulias/email-validator/src/Warning/ObsoleteDTEXT.php new file mode 100644 index 000000000..10f19e334 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/ObsoleteDTEXT.php @@ -0,0 +1,14 @@ +rfcNumber = 5322; + $this->message = 'Obsolete DTEXT in domain literal'; + } +} diff --git a/lib/egulias/email-validator/src/Warning/QuotedPart.php b/lib/egulias/email-validator/src/Warning/QuotedPart.php new file mode 100644 index 000000000..36a4265a5 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/QuotedPart.php @@ -0,0 +1,17 @@ +message = "Deprecated Quoted String found between $prevToken and $postToken"; + } +} diff --git a/lib/egulias/email-validator/src/Warning/QuotedString.php b/lib/egulias/email-validator/src/Warning/QuotedString.php new file mode 100644 index 000000000..817e4e84b --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/QuotedString.php @@ -0,0 +1,17 @@ +message = "Quoted String found between $prevToken and $postToken"; + } +} diff --git a/lib/egulias/email-validator/src/Warning/TLD.php b/lib/egulias/email-validator/src/Warning/TLD.php new file mode 100644 index 000000000..2338b9f44 --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/TLD.php @@ -0,0 +1,13 @@ +message = "RFC5321, TLD"; + } +} diff --git a/lib/egulias/email-validator/src/Warning/Warning.php b/lib/egulias/email-validator/src/Warning/Warning.php new file mode 100644 index 000000000..a2ee7b0de --- /dev/null +++ b/lib/egulias/email-validator/src/Warning/Warning.php @@ -0,0 +1,47 @@ +message; + } + + /** + * @return int + */ + public function code() + { + return static::CODE; + } + + /** + * @return int + */ + public function RFCNumber() + { + return $this->rfcNumber; + } + + public function __toString() + { + return $this->message() . " rfc: " . $this->rfcNumber . "interal code: " . static::CODE; + } +} diff --git a/lib/nikic/php-parser/.editorconfig b/lib/nikic/php-parser/.editorconfig deleted file mode 100644 index 9c76d0708..000000000 --- a/lib/nikic/php-parser/.editorconfig +++ /dev/null @@ -1,9 +0,0 @@ -root = true - -[*.y] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true -indent_style = space -indent_size = 4 diff --git a/lib/nikic/php-parser/grammar/php7.y b/lib/nikic/php-parser/grammar/php7.y index d9a450379..eac68d095 100644 --- a/lib/nikic/php-parser/grammar/php7.y +++ b/lib/nikic/php-parser/grammar/php7.y @@ -41,12 +41,12 @@ semi_reserved: | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC | T_READONLY ; -identifier_ex: +identifier_maybe_reserved: T_STRING { $$ = Node\Identifier[$1]; } | semi_reserved { $$ = Node\Identifier[$1]; } ; -identifier: +identifier_not_reserved: T_STRING { $$ = Node\Identifier[$1]; } ; @@ -181,14 +181,14 @@ non_empty_inline_use_declarations: unprefixed_use_declaration: namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } - | namespace_name T_AS identifier + | 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 + | legacy_namespace_name T_AS identifier_not_reserved { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } ; @@ -208,7 +208,7 @@ non_empty_constant_declaration_list: ; constant_declaration: - identifier '=' expr { $$ = Node\Const_[$1, $3]; } + identifier_not_reserved '=' expr { $$ = Node\Const_[$1, $3]; } ; class_const_list: @@ -221,7 +221,7 @@ non_empty_class_const_list: ; class_const: - identifier_ex '=' expr { $$ = Node\Const_[$1, $3]; } + identifier_maybe_reserved '=' expr { $$ = Node\Const_[$1, $3]; } ; inner_statement_list_ex: @@ -289,8 +289,8 @@ non_empty_statement: | 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 semi { $$ = Stmt\Goto_[$2]; } - | identifier ':' { $$ = Stmt\Label[$1]; } + | T_GOTO identifier_not_reserved semi { $$ = Stmt\Goto_[$2]; } + | identifier_not_reserved ':' { $$ = Stmt\Label[$1]; } | error { $$ = array(); /* means: no statement */ } ; @@ -351,22 +351,22 @@ block_or_error: ; function_declaration_statement: - T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type block_or_error + T_FUNCTION optional_ref identifier_not_reserved '(' 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 '(' parameter_list ')' optional_return_type block_or_error + | attributes T_FUNCTION optional_ref identifier_not_reserved '(' parameter_list ')' optional_return_type block_or_error { $$ = Stmt\Function_[$4, ['byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; } ; class_declaration_statement: - optional_attributes class_entry_type identifier extends_from implements_list '{' class_statement_list '}' + optional_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 interface_extends_list '{' class_statement_list '}' + | 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 '{' class_statement_list '}' + | optional_attributes T_TRAIT identifier_not_reserved '{' class_statement_list '}' { $$ = Stmt\Trait_[$3, ['stmts' => $5, 'attrGroups' => $1]]; } - | optional_attributes T_ENUM identifier enum_scalar_type implements_list '{' class_statement_list '}' + | 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); } ; @@ -436,7 +436,7 @@ non_empty_declare_list: ; declare_list_element: - identifier '=' expr { $$ = Stmt\DeclareDeclare[$1, $3]; } + identifier_not_reserved '=' expr { $$ = Stmt\DeclareDeclare[$1, $3]; } ; switch_case_list: @@ -530,24 +530,29 @@ non_empty_parameter_list: | non_empty_parameter_list ',' parameter { push($1, $3); } ; -optional_visibility_modifier: +optional_property_modifiers: /* empty */ { $$ = 0; } - | T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } + | 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_visibility_modifier optional_type_without_static + 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_visibility_modifier optional_type_without_static + | 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_visibility_modifier optional_type_without_static + | 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); } ; @@ -556,6 +561,7 @@ type_expr: type { $$ = $1; } | '?' type { $$ = Node\NullableType[$2]; } | union_type { $$ = Node\UnionType[$1]; } + | intersection_type { $$ = Node\IntersectionType[$1]; } ; type: @@ -579,10 +585,24 @@ union_type_without_static: | union_type_without_static '|' type_without_static { push($1, $3); } ; +intersection_type: + type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { init($1, $3); } + | intersection_type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type + { push($1, $3); } +; + +intersection_type_without_static: + type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static + { init($1, $3); } + | intersection_type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static + { push($1, $3); } +; + 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 { $$ = Node\IntersectionType[$1]; } ; optional_type_without_static: @@ -599,6 +619,11 @@ optional_return_type: argument_list: '(' ')' { $$ = array(); } | '(' non_empty_argument_list optional_comma ')' { $$ = $2; } + | '(' variadic_placeholder ')' { init($2); } +; + +variadic_placeholder: + T_ELLIPSIS { $$ = Node\VariadicPlaceholder[]; } ; non_empty_argument_list: @@ -610,7 +635,7 @@ argument: expr { $$ = Node\Arg[$1, false, false]; } | ampersand variable { $$ = Node\Arg[$2, true, false]; } | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } - | identifier_ex ':' expr + | identifier_maybe_reserved ':' expr { $$ = new Node\Arg($3, false, false, attributes(), $1); } ; @@ -659,11 +684,12 @@ class_statement: | 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_ex '(' parameter_list ')' optional_return_type method_body + | 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 enum_case_expr semi + | optional_attributes T_CASE identifier_maybe_reserved enum_case_expr semi { $$ = Stmt\EnumCase[$3, $4, $1]; } | error { $$ = null; /* will be skipped */ } ; @@ -681,22 +707,22 @@ trait_adaptation_list: 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 ';' + | 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 ';' + | 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_ex { $$ = array($1, $3); } + name T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved { $$ = array($1, $3); } ; trait_method_reference: trait_method_reference_fully_qualified { $$ = $1; } - | identifier_ex { $$ = array(null, $1); } + | identifier_maybe_reserved { $$ = array(null, $1); } ; method_body: @@ -969,7 +995,7 @@ constant: ; class_constant: - class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex + 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. */ @@ -1088,13 +1114,13 @@ new_variable: ; member_name: - identifier_ex { $$ = $1; } + identifier_maybe_reserved { $$ = $1; } | '{' expr '}' { $$ = $2; } | simple_variable { $$ = $1; } ; property_name: - identifier { $$ = $1; } + identifier_not_reserved { $$ = $1; } | '{' expr '}' { $$ = $2; } | simple_variable { $$ = $1; } | error { $$ = Expr\Error[]; $this->errorState = 2; } @@ -1149,8 +1175,10 @@ encaps_str_varname: encaps_var: plain_variable { $$ = $1; } | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | plain_variable T_OBJECT_OPERATOR identifier { $$ = Expr\PropertyFetch[$1, $3]; } - | plain_variable T_NULLSAFE_OBJECT_OPERATOR identifier { $$ = Expr\NullsafePropertyFetch[$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 ']' '}' diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php b/lib/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php new file mode 100644 index 000000000..02fa83e62 --- /dev/null +++ b/lib/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->attributes, + $this->attributeGroups + ); + } +} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Enum_.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Enum_.php new file mode 100644 index 000000000..be7eef95f --- /dev/null +++ b/lib/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/lib/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php b/lib/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php index 8e7db399d..98ea9d336 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php +++ b/lib/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php @@ -61,8 +61,7 @@ abstract class FunctionLike extends Declaration /** * Sets the return type for PHP 7. * - * @param string|Node\Name|Node\NullableType $type One of array, callable, string, int, float, - * bool, iterable, or a class/interface name. + * @param string|Node\Name|Node\Identifier|Node\ComplexType $type * * @return $this The builder instance (for fluid interface) */ diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Param.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Param.php index 0ea91683c..de9aae7e5 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Param.php +++ b/lib/nikic/php-parser/lib/PhpParser/Builder/Param.php @@ -47,7 +47,7 @@ class Param implements PhpParser\Builder /** * Sets type for the parameter. * - * @param string|Node\Name|Node\NullableType|Node\UnionType $type Parameter type + * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type * * @return $this The builder instance (for fluid interface) */ @@ -63,7 +63,7 @@ class Param implements PhpParser\Builder /** * Sets type for the parameter. * - * @param string|Node\Name|Node\NullableType|Node\UnionType $type Parameter type + * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type * * @return $this The builder instance (for fluid interface) * diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Property.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Property.php index 90ee4b0ba..68e318565 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Property.php +++ b/lib/nikic/php-parser/lib/PhpParser/Builder/Property.php @@ -7,8 +7,8 @@ use PhpParser\BuilderHelpers; use PhpParser\Node; use PhpParser\Node\Identifier; use PhpParser\Node\Name; -use PhpParser\Node\NullableType; use PhpParser\Node\Stmt; +use PhpParser\Node\ComplexType; class Property implements PhpParser\Builder { @@ -119,7 +119,7 @@ class Property implements PhpParser\Builder /** * Sets the property type for PHP 7.4+. * - * @param string|Name|NullableType|Identifier $type + * @param string|Name|Identifier|ComplexType $type * * @return $this */ diff --git a/lib/nikic/php-parser/lib/PhpParser/BuilderFactory.php b/lib/nikic/php-parser/lib/PhpParser/BuilderFactory.php index 6a6b7b07b..fef2579b3 100644 --- a/lib/nikic/php-parser/lib/PhpParser/BuilderFactory.php +++ b/lib/nikic/php-parser/lib/PhpParser/BuilderFactory.php @@ -71,6 +71,17 @@ class BuilderFactory 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. * @@ -188,6 +199,17 @@ class BuilderFactory 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. * @@ -311,7 +333,7 @@ class BuilderFactory public function constFetch($name) : Expr\ConstFetch { return new Expr\ConstFetch(BuilderHelpers::normalizeName($name)); } - + /** * Creates a property fetch node. * diff --git a/lib/nikic/php-parser/lib/PhpParser/BuilderHelpers.php b/lib/nikic/php-parser/lib/PhpParser/BuilderHelpers.php index c6d8f1613..2f0e91273 100644 --- a/lib/nikic/php-parser/lib/PhpParser/BuilderHelpers.php +++ b/lib/nikic/php-parser/lib/PhpParser/BuilderHelpers.php @@ -2,13 +2,13 @@ namespace PhpParser; +use PhpParser\Node\ComplexType; use PhpParser\Node\Expr; use PhpParser\Node\Identifier; use PhpParser\Node\Name; use PhpParser\Node\NullableType; use PhpParser\Node\Scalar; use PhpParser\Node\Stmt; -use PhpParser\Node\UnionType; /** * This class defines helpers used in the implementation of builders. Don't use it directly. @@ -104,29 +104,6 @@ final class BuilderHelpers * @return Name The normalized name */ public static function normalizeName($name) : Name { - return self::normalizeNameCommon($name, false); - } - - /** - * 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) { - return self::normalizeNameCommon($name, true); - } - - /** - * Normalizes a name: Converts string names to Name nodes, optionally allowing expressions. - * - * @param Expr|Name|string $name The name to normalize - * @param bool $allowExpr Whether to also allow expressions - * - * @return Name|Expr The normalized name, or expression (if allowed) - */ - private static function normalizeNameCommon($name, bool $allowExpr) { if ($name instanceof Name) { return $name; } @@ -147,16 +124,28 @@ final class BuilderHelpers return new Name($name); } - if ($allowExpr) { - if ($name instanceof Expr) { - return $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' ); } - throw new \LogicException('Name must be a string or an instance of Node\Name'); + return self::normalizeName($name); } /** @@ -165,18 +154,18 @@ final class BuilderHelpers * In particular, builtin types become Identifiers, custom types become Names and nullables * are wrapped in NullableType nodes. * - * @param string|Name|Identifier|NullableType|UnionType $type The type to normalize + * @param string|Name|Identifier|ComplexType $type The type to normalize * - * @return Name|Identifier|NullableType|UnionType The normalized type + * @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 NullableType && !$type instanceof UnionType + !$type instanceof ComplexType ) { throw new \LogicException( - 'Type must be a string, or an instance of Name, Identifier, NullableType or UnionType' + 'Type must be a string, or an instance of Name, Identifier or ComplexType' ); } return $type; diff --git a/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php b/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php index 7f02e6f24..7131c3d25 100644 --- a/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php +++ b/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php @@ -2,6 +2,7 @@ namespace PhpParser; +use function array_merge; use PhpParser\Node\Expr; use PhpParser\Node\Scalar; @@ -150,6 +151,8 @@ class ConstExprEvaluator 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); } diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php index a8f4e334a..5c56e026b 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php +++ b/lib/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php @@ -8,6 +8,7 @@ use PhpParser\Lexer; use PhpParser\Lexer\TokenEmulator\AttributeEmulator; use PhpParser\Lexer\TokenEmulator\EnumTokenEmulator; use PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator; +use PhpParser\Lexer\TokenEmulator\ExplicitOctalEmulator; use PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator; use PhpParser\Lexer\TokenEmulator\FnTokenEmulator; use PhpParser\Lexer\TokenEmulator\MatchTokenEmulator; @@ -36,7 +37,7 @@ class Emulative extends Lexer /** * @param mixed[] $options Lexer options. In addition to the usual options, * accepts a 'phpVersion' string that specifies the - * version to emulated. Defaults to newest supported. + * version to emulate. Defaults to newest supported. */ public function __construct(array $options = []) { @@ -55,6 +56,7 @@ class Emulative extends Lexer new AttributeEmulator(), new EnumTokenEmulator(), new ReadonlyTokenEmulator(), + new ExplicitOctalEmulator(), ]; // Collect emulators that are relevant for the PHP version we're running diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php new file mode 100644 index 000000000..f5f6805b8 --- /dev/null +++ b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php @@ -0,0 +1,44 @@ +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/lib/nikic/php-parser/lib/PhpParser/Node/Arg.php b/lib/nikic/php-parser/lib/PhpParser/Node/Arg.php index b25b0904a..bcf130e68 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Arg.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Arg.php @@ -2,6 +2,7 @@ namespace PhpParser\Node; +use PhpParser\Node\VariadicPlaceholder; use PhpParser\NodeAbstract; class Arg extends NodeAbstract diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/ComplexType.php b/lib/nikic/php-parser/lib/PhpParser/Node/ComplexType.php new file mode 100644 index 000000000..9505532ae --- /dev/null +++ b/lib/nikic/php-parser/lib/PhpParser/Node/ComplexType.php @@ -0,0 +1,14 @@ +params = $subNodes['params'] ?? []; $returnType = $subNodes['returnType'] ?? null; $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; - $this->expr = $subNodes['expr'] ?? null; + $this->expr = $subNodes['expr']; $this->attrGroups = $subNodes['attrGroups'] ?? []; } diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php new file mode 100644 index 000000000..78e1cf349 --- /dev/null +++ b/lib/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/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php index 56e621f25..56ddea6aa 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php @@ -16,7 +16,7 @@ class Closure extends Expr implements FunctionLike public $params; /** @var ClosureUse[] use()s */ public $uses; - /** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType Return type */ + /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php index 1e8afa559..2de4d0dd5 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php @@ -5,19 +5,19 @@ namespace PhpParser\Node\Expr; use PhpParser\Node; use PhpParser\Node\Expr; -class FuncCall extends Expr +class FuncCall extends CallLike { /** @var Node\Name|Expr Function name */ public $name; - /** @var Node\Arg[] Arguments */ + /** @var array Arguments */ public $args; /** * Constructs a function call node. * - * @param Node\Name|Expr $name Function name - * @param Node\Arg[] $args Arguments - * @param array $attributes Additional attributes + * @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; @@ -32,4 +32,8 @@ class FuncCall extends Expr public function getType() : string { return 'Expr_FuncCall'; } + + public function getRawArgs(): array { + return $this->args; + } } diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php index bd81bb43f..49ca48356 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php @@ -5,23 +5,24 @@ namespace PhpParser\Node\Expr; use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Identifier; +use PhpParser\Node\VariadicPlaceholder; -class MethodCall extends Expr +class MethodCall extends CallLike { /** @var Expr Variable holding object */ public $var; /** @var Identifier|Expr Method name */ public $name; - /** @var Arg[] Arguments */ + /** @var array Arguments */ public $args; /** * Constructs a function call node. * - * @param Expr $var Variable holding object - * @param string|Identifier|Expr $name Method name - * @param Arg[] $args Arguments - * @param array $attributes Additional attributes + * @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; @@ -37,4 +38,8 @@ class MethodCall extends Expr public function getType() : string { return 'Expr_MethodCall'; } + + public function getRawArgs(): array { + return $this->args; + } } diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php index c86f0c601..e2bb64928 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php @@ -3,20 +3,22 @@ namespace PhpParser\Node\Expr; use PhpParser\Node; +use PhpParser\Node\Arg; use PhpParser\Node\Expr; +use PhpParser\Node\VariadicPlaceholder; -class New_ extends Expr +class New_ extends CallLike { /** @var Node\Name|Expr|Node\Stmt\Class_ Class name */ public $class; - /** @var Node\Arg[] Arguments */ + /** @var array 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 Node\Arg[] $args Arguments + * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct($class, array $args = [], array $attributes = []) { @@ -32,4 +34,8 @@ class New_ extends Expr public function getType() : string { return 'Expr_New'; } + + public function getRawArgs(): array { + return $this->args; + } } diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php index 361e44622..07a571fd8 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php @@ -5,23 +5,24 @@ namespace PhpParser\Node\Expr; use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Identifier; +use PhpParser\Node\VariadicPlaceholder; -class NullsafeMethodCall extends Expr +class NullsafeMethodCall extends CallLike { /** @var Expr Variable holding object */ public $var; /** @var Identifier|Expr Method name */ public $name; - /** @var Arg[] Arguments */ + /** @var array Arguments */ public $args; /** * Constructs a nullsafe method call node. * - * @param Expr $var Variable holding object - * @param string|Identifier|Expr $name Method name - * @param Arg[] $args Arguments - * @param array $attributes Additional attributes + * @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; @@ -37,4 +38,8 @@ class NullsafeMethodCall extends Expr public function getType() : string { return 'Expr_NullsafeMethodCall'; } + + public function getRawArgs(): array { + return $this->args; + } } diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php index 9883f5af5..d0d099c47 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php @@ -3,25 +3,27 @@ namespace PhpParser\Node\Expr; use PhpParser\Node; +use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Identifier; +use PhpParser\Node\VariadicPlaceholder; -class StaticCall extends Expr +class StaticCall extends CallLike { /** @var Node\Name|Expr Class name */ public $class; /** @var Identifier|Expr Method name */ public $name; - /** @var Node\Arg[] Arguments */ + /** @var array Arguments */ public $args; /** * Constructs a static method call node. * - * @param Node\Name|Expr $class Class name - * @param string|Identifier|Expr $name Method name - * @param Node\Arg[] $args Arguments - * @param array $attributes Additional attributes + * @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; @@ -37,4 +39,8 @@ class StaticCall extends Expr public function getType() : string { return 'Expr_StaticCall'; } + + public function getRawArgs(): array { + return $this->args; + } } diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php b/lib/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php index bbcf53e55..5a825e731 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php @@ -23,7 +23,7 @@ interface FunctionLike extends Node /** * Get the declared return type or null * - * @return null|Identifier|Name|NullableType|UnionType + * @return null|Identifier|Name|ComplexType */ public function getReturnType(); diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php b/lib/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php new file mode 100644 index 000000000..9208e1392 --- /dev/null +++ b/lib/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/lib/nikic/php-parser/lib/PhpParser/Node/NullableType.php b/lib/nikic/php-parser/lib/PhpParser/Node/NullableType.php index 36463657e..d68e26a38 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/NullableType.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/NullableType.php @@ -2,9 +2,7 @@ namespace PhpParser\Node; -use PhpParser\NodeAbstract; - -class NullableType extends NodeAbstract +class NullableType extends ComplexType { /** @var Identifier|Name Type */ public $type; diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Param.php b/lib/nikic/php-parser/lib/PhpParser/Node/Param.php index 315b5f24f..1e90b7944 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Param.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Param.php @@ -6,7 +6,7 @@ use PhpParser\NodeAbstract; class Param extends NodeAbstract { - /** @var null|Identifier|Name|NullableType|UnionType Type declaration */ + /** @var null|Identifier|Name|ComplexType Type declaration */ public $type; /** @var bool Whether parameter is passed by reference */ public $byRef; @@ -24,14 +24,14 @@ class Param extends NodeAbstract /** * Constructs a parameter node. * - * @param Expr\Variable|Expr\Error $var Parameter variable - * @param null|Expr $default Default value - * @param null|string|Identifier|Name|NullableType|UnionType $type Type declaration - * @param bool $byRef Whether is passed by reference - * @param bool $variadic Whether this is a variadic argument - * @param array $attributes Additional attributes - * @param int $flags Optional visibility flags - * @param AttributeGroup[] $attrGroups PHP attribute groups + * @param Expr\Variable|Expr\Error $var Parameter variable + * @param null|Expr $default Default value + * @param null|string|Identifier|Name|ComplexType $type Type declaration + * @param bool $byRef Whether is passed by reference + * @param bool $variadic Whether this is a variadic argument + * @param array $attributes Additional attributes + * @param int $flags Optional visibility flags + * @param AttributeGroup[] $attrGroups PHP attribute groups */ public function __construct( $var, Expr $default = null, $type = null, diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php index b33943547..f17dd1f8a 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php @@ -62,6 +62,11 @@ class LNumber extends Scalar 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); diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php index 840c4f67e..6c3369172 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php @@ -4,9 +4,6 @@ namespace PhpParser\Node\Stmt; use PhpParser\Node; -/** - * @property Node\Name $namespacedName Namespaced name (if using NameResolver) - */ abstract class ClassLike extends Node\Stmt { /** @var Node\Identifier|null Name */ @@ -16,6 +13,9 @@ abstract class ClassLike extends Node\Stmt /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; + /** @var Node\Name Namespaced name (if using NameResolver) */ + public $namespacedName; + /** * @return TraitUse[] */ diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php index 92157fab2..09b877a92 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php @@ -15,7 +15,7 @@ class ClassMethod extends Node\Stmt implements FunctionLike public $name; /** @var Node\Param[] Parameters */ public $params; - /** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType Return type */ + /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[]|null Statements */ public $stmts; diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php index f08481fae..abb7ee5c8 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php @@ -5,9 +5,6 @@ namespace PhpParser\Node\Stmt; use PhpParser\Node; use PhpParser\Node\FunctionLike; -/** - * @property Node\Name $namespacedName Namespaced name (if using NameResolver) - */ class Function_ extends Node\Stmt implements FunctionLike { /** @var bool Whether function returns by reference */ @@ -16,13 +13,16 @@ class Function_ extends Node\Stmt implements FunctionLike public $name; /** @var Node\Param[] Parameters */ public $params; - /** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType Return type */ + /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ public $returnType; /** @var Node\Stmt[] Statements */ public $stmts; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; + /** @var Node\Name Namespaced name (if using NameResolver) */ + public $namespacedName; + /** * Constructs a function node. * diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php index 4f04805d2..bc781bbff 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php @@ -3,10 +3,9 @@ namespace PhpParser\Node\Stmt; use PhpParser\Node; +use PhpParser\Node\ComplexType; use PhpParser\Node\Identifier; use PhpParser\Node\Name; -use PhpParser\Node\NullableType; -use PhpParser\Node\UnionType; class Property extends Node\Stmt { @@ -14,7 +13,7 @@ class Property extends Node\Stmt public $flags; /** @var PropertyProperty[] Properties */ public $props; - /** @var null|Identifier|Name|NullableType|UnionType Type declaration */ + /** @var null|Identifier|Name|ComplexType Type declaration */ public $type; /** @var Node\AttributeGroup[] PHP attribute groups */ public $attrGroups; @@ -22,11 +21,11 @@ class Property extends Node\Stmt /** * Constructs a class property list node. * - * @param int $flags Modifiers - * @param PropertyProperty[] $props Properties - * @param array $attributes Additional attributes - * @param null|string|Identifier|Name|NullableType|UnionType $type Type declaration - * @param Node\AttributeGroup[] $attrGroups PHP attribute groups + * @param int $flags Modifiers + * @param PropertyProperty[] $props Properties + * @param array $attributes Additional attributes + * @param null|string|Identifier|Name|ComplexType $type Type declaration + * @param Node\AttributeGroup[] $attrGroups PHP attribute groups */ public function __construct(int $flags, array $props, array $attributes = [], $type = null, array $attrGroups = []) { $this->attributes = $attributes; diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/UnionType.php b/lib/nikic/php-parser/lib/PhpParser/Node/UnionType.php index c8f45235d..61c2d8106 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Node/UnionType.php +++ b/lib/nikic/php-parser/lib/PhpParser/Node/UnionType.php @@ -2,9 +2,7 @@ namespace PhpParser\Node; -use PhpParser\NodeAbstract; - -class UnionType extends NodeAbstract +class UnionType extends ComplexType { /** @var (Identifier|Name)[] Types */ public $types; diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php b/lib/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php new file mode 100644 index 000000000..403a24df2 --- /dev/null +++ b/lib/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php @@ -0,0 +1,27 @@ +attributes = $attributes; + } + + public function getType(): string { + return 'VariadicPlaceholder'; + } + + public function getSubNodeNames(): array { + return []; + } +} \ No newline at end of file diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php b/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php index 79bbc4577..8e259c57b 100644 --- a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php +++ b/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php @@ -189,7 +189,7 @@ class NameResolver extends NodeVisitorAbstract $node->type = $this->resolveType($node->type); return $node; } - if ($node instanceof Node\UnionType) { + if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) { foreach ($node->types as &$type) { $type = $this->resolveType($type); } diff --git a/lib/nikic/php-parser/lib/PhpParser/Parser/Php7.php b/lib/nikic/php-parser/lib/PhpParser/Parser/Php7.php index 75fc06db7..7a0854b30 100644 --- a/lib/nikic/php-parser/lib/PhpParser/Parser/Php7.php +++ b/lib/nikic/php-parser/lib/PhpParser/Parser/Php7.php @@ -18,16 +18,16 @@ use PhpParser\Node\Stmt; class Php7 extends \PhpParser\ParserAbstract { protected $tokenToSymbolMapSize = 396; - protected $actionTableSize = 1187; - protected $gotoTableSize = 579; + protected $actionTableSize = 1196; + protected $gotoTableSize = 545; protected $invalidSymbol = 168; protected $errorSymbol = 1; protected $defaultAction = -32766; protected $unexpectedTokenRule = 32767; - protected $YY2TBLSTATE = 415; - protected $numNonLeafStates = 702; + protected $YY2TBLSTATE = 420; + protected $numNonLeafStates = 710; protected $symbolToName = array( "EOF", @@ -244,254 +244,256 @@ class Php7 extends \PhpParser\ParserAbstract ); protected $action = array( - 131, 132, 133, 563, 134, 135, 0, 714, 715, 716, - 136, 36, 977, 976, 975, 978,-32766,-32766,-32766,-32767, - -32767,-32767,-32767, 100, 101, 102, 103, 104, 1051, 1052, - 1053, 1050, 1049, 1048, 1054, 708, 707,-32766,-32766,-32766, + 132, 133, 134, 569, 135, 136, 0, 722, 723, 724, + 137, 37, 834, 911, 835, 469,-32766,-32766,-32766,-32767, + -32767,-32767,-32767, 101, 102, 103, 104, 105, 1068, 1069, + 1070, 1067, 1066, 1065, 1071, 716, 715,-32766,-32766,-32766, -32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, - -32767, 539, 540, 903, 2, 717,-32766,-32766,-32766, 988, - 989, -88, 914, 440, 441, 442, 365, 366, 462, 265, - 137, 391, 721, 722, 723, 724, 409,-32766, 415,-32766, - -32766,-32766,-32766,-32766, -305, 725, 726, 727, 728, 729, - 730, 731, 732, 733, 734, 735, 755, 564, 756, 757, - 758, 759, 747, 748, 331, 332, 750, 751, 736, 737, - 738, 740, 741, 742, 341, 782, 783, 784, 785, 786, - 787, 743, 744, 565, 566, 776, 767, 765, 766, 779, - 762, 763, 981, 415, 567, 568, 761, 569, 570, 571, - 572, 573, 574, -193, -566, 535, 485, 790, 764, 575, - 576, -566, 138,-32766,-32766,-32766, 131, 132, 133, 563, - 134, 135, 1002, 714, 715, 716, 136, 36, 1043,-32766, - -32766,-32766, 799, -86,-32766, 1276,-32766,-32766,-32766,-32766, - -32766,-32766,-32766, 1051, 1052, 1053, 1050, 1049, 1048, 1054, - -32766, 708, 707,-32766,-32766,-32766, 1241, 238, 463,-32766, - -32766,-32766,-32766,-32766,-32766, 883, 1213, 125, 1176, 1175, - 1177, 717, 801, 689,-32766, 1029,-32766,-32766,-32766,-32766, - -32766, -192,-32766,-32766,-32766, 265, 137, 391, 721, 722, - 723, 724, 883, 945, 415, 680, 12, 34, 247, -86, - -305, 725, 726, 727, 728, 729, 730, 731, 732, 733, - 734, 735, 755, 564, 756, 757, 758, 759, 747, 748, - 331, 332, 750, 751, 736, 737, 738, 740, 741, 742, - 341, 782, 783, 784, 785, 786, 787, 743, 744, 565, - 566, 776, 767, 765, 766, 779, 762, 763, 873, 585, - 567, 568, 761, 569, 570, 571, 572, 573, 574, -193, - 81, 82, 83, -566, 764, 575, 576, -566, 138, 739, - 709, 710, 711, 712, 713, 873, 714, 715, 716, 752, - 753, 35, 33, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, -264, 267,-32766, - -32766,-32766,-32766, 105, 106, 107, 80, 267, 127, 1001, - 108, 946, 314, 885, 717, 675, 367, 366, 143, 108, - 800,-32766, 1027,-32766,-32766, 148, 409, -192, 718, 719, - 720, 721, 722, 723, 724, 237, 1181, 788, 276, -517, - 885, 315, 675, 149, 725, 726, 727, 728, 729, 730, - 731, 732, 733, 734, 735, 755, 778, 756, 757, 758, - 759, 747, 748, 749, 777, 750, 751, 736, 737, 738, - 740, 741, 742, 781, 782, 783, 784, 785, 786, 787, - 743, 744, 745, 746, 776, 767, 765, 766, 779, 762, - 763,-32766,-32766, 754, 760, 761, 768, 769, 771, 770, - 772, 773, 251, -517, -517, 448, 449, 764, 775, 774, - 48, 49, 50, 494, 51, 52, 795, 799, -517, 591, - 53, 54, -111, 55, 986, 708, 707, -111, 792, -111, - -517, 298, -523, 986, 294, 631, 24, -111, -111, -111, - -111, -111, -111, -111, -111, 988, 989, 300, 1286, 1261, - -343, 1287, -343, 1174, 988, 989, 1260, 312, 56, 57, - -32766,-32766,-32766, -111, 58, 1201, 59, 244, 245, 60, - 61, 62, 63, 64, 65, 66, 67, -516, 26, 266, - 68, 429, 495, -319, 647, 648, 1207, 1208, 496, 1172, - 799, 1181, 796, 287, 1205, 40, 23, 497, 73, 498, - 328, 499, 314, 500, 794, 329, 501, 502, 826, 677, - 827, 42, 43, 430, 362, 361, 883, 44, 503, 147, - 394, -16, -557, 353, 327, 355, -557, 1181, 1176, 1175, - 1177, -518, 504, 505, 506, 359, -515, 1257, 47, 363, - 364, -516, -516, 374, 507, 508, 799, 1195, 1196, 1197, - 1198, 1192, 1193, 286, -563, 425, -516, 798, 151, 1199, - 1194, -563, 426, 1176, 1175, 1177, 287, 883, -516, 427, - -522, 69, 799, 310, 311, 314, 30, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - -153, -153, -153, 368, 369, -518, -518, 681, 428, 873, - -515, -515, 290, 291, 883, -153, 805, -153, 799, -153, - -518, -153, 708, 707, 152, -515, 790, 358, -111, 1088, - 1090, 360, -518, 153, 883, 139, 376, -515, 11, 126, - -515, 314, -111, -111, 682, 155, 279, -520, 102, 103, - 104, 31, 859, -111, -111, -111, -111, 46, 287,-32766, - 873, 623, 624, 73, 684, 1174, 826, 314, 827, 1028, - -79, 700,-32766,-32766,-32766, 122,-32766, 123,-32766, 128, - -32766, 708, 707,-32766, 885, 883, 675, -153,-32766,-32766, - -32766, 708, 707, 129,-32766,-32766, 142, 873, 156, 73, - -32766, 406, 157, 314, -515, -515, 158, 140, 159,-32766, - -75, -520, -520, 314, 26, 691, -73, 873, -72, -515, - -71, 288, 289, -563, -70, -69, 799, -563,-32766, -68, - 1205, -515,-32766, -67, 1174, 885, -66, 675, -520, 72, - -47,-32766,-32766,-32766, -18,-32766, 146,-32766, 124,-32766, - 268, 275,-32766, 988, 989, 690, -51,-32766,-32766,-32766, - 693, 882, 145,-32766,-32766, 899, 108, 277, 873,-32766, - 406, 278, 931, 280, 675, 281, 321, 144,-32766, 267, - 507, 508, 799, 1195, 1196, 1197, 1198, 1192, 1193, 655, - 130, 790, 885, 1288, 675, 1199, 1194, 543, 1058,-32766, - 650, 13,-32766, 537, 632, 1174, 424, 71, 621, 915, - 311, 314,-32766,-32766,-32766, 668,-32766, 637,-32766,-32766, - -32766, 293, 1212,-32766, 916, 445, 638, 549,-32766,-32766, - -32766, 473, -481,-32766,-32766,-32766, -4, 883, -551, 1174, - -32766, 406, 651, 885, 589, 675,-32766,-32766,-32766,-32766, - -32766, 295,-32766, 901,-32766, 0, 798,-32766, 0, 0, - 0, 0,-32766,-32766,-32766,-32766, 0, 292,-32766,-32766, - 0, 1174, 0, 0,-32766, 406, 299, 0,-32766,-32766, - -32766, 0,-32766,-32766,-32766, 1214,-32766, 0, 0,-32766, - 0, 287, -471, 468,-32766,-32766,-32766,-32766, 7, 15, - -32766,-32766, 357, 1174, 555, 38,-32766, 406, 1202, 883, - -32766,-32766,-32766, 39,-32766,-32766,-32766, 697,-32766, 698, - 873,-32766, 864, 955, 932, 939,-32766,-32766,-32766, 929, - 940, 862,-32766,-32766, 927, 1032, 1035, 1036,-32766, 406, - 1033, 1034, 360, 1040, 420, 883, 810,-32766, 1227, 285, - 1245, 694, 1279, -111, -111, 626, 860, 32, 309, 356, - 676, 679, 683, 818, -111, -111, -111, -111, 685, 686, - -32766, 687, 688, 692, 678, 1206, 1174, 1283, 1285, 821, - 820, 829, 908,-32766,-32766,-32766, 9,-32766, 947,-32766, - 828,-32766, 873, 1284,-32766, 885, 907, 675, -4,-32766, - -32766,-32766, 909, 906, 1160,-32766,-32766, 892, -242, -242, - -242,-32766, 406, 902, 360, 26, 890, 937, 938, 1282, - -32766, 1239, 1228, 1246, 1252, -111, -111, 799, 873, 1255, - -267, 1205, -549, -523, -522, 859, -111, -111, -111, -111, - -521, 1, 27, 28, -241, -241, -241, 37, 41, 45, - 360, 70, 74, 75, 76, 77, 78, 79, 141, 0, - 150, -111, -111, 154, 243, 316, 342, 885, 343, 675, - -242, 859, -111, -111, -111, -111, 344, 345, 346, 347, - 348, 349, 508, 350, 1195, 1196, 1197, 1198, 1192, 1193, - 351, 352, 354, 421, 0, -265, 1199, 1194, -264, 17, - 18, 19, 20, 885, 22, 675, -241, 393, 71, 314, - 464, 311, 314, 465, 472, 475, 476, 477, 478, 482, - 483, 484, 492, 662, 1185, 1128, 1203, 1003, 1164, -269, - -103, 16, 21, 25, 284, 392, 582, 586, 613, 667, - 1132, 1180, 1129, 1258, 0, -485, 1145 + -32767, 545, 546,-32766,-32766, 725,-32766,-32766,-32766, 998, + 999, 806, 922, 447, 448, 449, 370, 371, 2, 267, + 138, 396, 729, 730, 731, 732, 414,-32766, 420,-32766, + -32766,-32766,-32766,-32766, 990, 733, 734, 735, 736, 737, + 738, 739, 740, 741, 742, 743, 763, 570, 764, 765, + 766, 767, 755, 756, 336, 337, 758, 759, 744, 745, + 746, 748, 749, 750, 346, 790, 791, 792, 793, 794, + 795, 751, 752, 571, 572, 784, 775, 773, 774, 787, + 770, 771, 283, 420, 573, 574, 769, 575, 576, 577, + 578, 579, 580, 598, -575, 470, 14, 798, 772, 581, + 582, -575, 139,-32766,-32766,-32766, 132, 133, 134, 569, + 135, 136, 1017, 722, 723, 724, 137, 37, 1060,-32766, + -32766,-32766, 1303, 696,-32766, 1304,-32766,-32766,-32766,-32766, + -32766,-32766,-32766, 1068, 1069, 1070, 1067, 1066, 1065, 1071, + -32766, 716, 715, 372, 371, 1258,-32766,-32766,-32766, -572, + 106, 107, 108, 414, 270, 891, -572, 240, 1193, 1192, + 1194, 725,-32766,-32766,-32766, 1046, 109,-32766,-32766,-32766, + -32766, 986, 985, 984, 987, 267, 138, 396, 729, 730, + 731, 732, 12,-32766, 420,-32766,-32766,-32766,-32766, 998, + 999, 733, 734, 735, 736, 737, 738, 739, 740, 741, + 742, 743, 763, 570, 764, 765, 766, 767, 755, 756, + 336, 337, 758, 759, 744, 745, 746, 748, 749, 750, + 346, 790, 791, 792, 793, 794, 795, 751, 752, 571, + 572, 784, 775, 773, 774, 787, 770, 771, 881, 321, + 573, 574, 769, 575, 576, 577, 578, 579, 580,-32766, + 82, 83, 84, -575, 772, 581, 582, -575, 148, 747, + 717, 718, 719, 720, 721, 1278, 722, 723, 724, 760, + 761, 36, 1277, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 996, 270, 150, + -32766,-32766,-32766, 455, 456, 81, 34, -264, -572, 1016, + 109, 320, -572, 893, 725, 682, 803, 128, 998, 999, + 592,-32766, 1044,-32766,-32766,-32766, 809, 151, 726, 727, + 728, 729, 730, 731, 732, -88, 1198, 796, 278, -526, + 283,-32766,-32766,-32766, 733, 734, 735, 736, 737, 738, + 739, 740, 741, 742, 743, 763, 786, 764, 765, 766, + 767, 755, 756, 757, 785, 758, 759, 744, 745, 746, + 748, 749, 750, 789, 790, 791, 792, 793, 794, 795, + 751, 752, 753, 754, 784, 775, 773, 774, 787, 770, + 771, 144, 804, 762, 768, 769, 776, 777, 779, 778, + 780, 781, -314, -526, -526, -193, -192, 772, 783, 782, + 49, 50, 51, 500, 52, 53, 239, 807, -526, -86, + 54, 55, -111, 56, 996, 253,-32766, -111, 800, -111, + -526, 541, -532, -352, 300, -352, 304, -111, -111, -111, + -111, -111, -111, -111, -111, 998, 999, 998, 999, 153, + -32766,-32766,-32766, 1191, 807, 126, 306, 1293, 57, 58, + 103, 104, 105, -111, 59, 1218, 60, 246, 247, 61, + 62, 63, 64, 65, 66, 67, 68, -525, 27, 268, + 69, 436, 501, -328, 808, -86, 1224, 1225, 502, 1189, + 807, 1198, 1230, 293, 1222, 41, 24, 503, 74, 504, + 953, 505, 320, 506, 802, 154, 507, 508, 279, 684, + 280, 43, 44, 437, 367, 366, 891, 45, 509, 35, + 249, -16, -566, 358, 332, 318, -566, 1198, 1193, 1192, + 1194, -527, 510, 511, 512, 333, -524, 1274, 48, 716, + 715, -525, -525, 334, 513, 514, 807, 1212, 1213, 1214, + 1215, 1209, 1210, 292, 360, 284, -525, 285, -314, 1216, + 1211, -193, -192, 1193, 1192, 1194, 293, 891, -525, 364, + -531, 70, 807, 316, 317, 320, 31, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + -153, -153, -153, 638, 25, -527, -527, 687, 379, 881, + -524, -524, 296, 297, 891, -153, 432, -153, 807, -153, + -527, -153, 716, 715, 433, -524, 798, 363, -111, 1105, + 1107, 365, -527, 434, 891, 140, 435, -524, 954, 127, + -524, 320, -111, -111, 688, 813, 381, -529, 11, 834, + 155, 835, 867, -111, -111, -111, -111, 47, 293,-32766, + 881, 654, 655, 74, 689, 1191, 1045, 320, 708, 149, + 399, 157,-32766,-32766,-32766, 32,-32766, -79,-32766, 123, + -32766, 716, 715,-32766, 893, 891, 682, -153,-32766,-32766, + -32766, 716, 715, 891,-32766,-32766, 124, 881, 129, 74, + -32766, 411, 130, 320, -524, -524, 143, 141, -75,-32766, + 158, -529, -529, 320, 27, 691, 159, 881, 160, -524, + 161, 294, 295, 698, 368, 369, 807, -73,-32766, -72, + 1222, -524, 373, 374, 1191, 893, -71, 682, -529, 73, + -70,-32766,-32766,-32766, -69,-32766, -68,-32766, 125,-32766, + 630, 631,-32766, -67, -66, -47, -51,-32766,-32766,-32766, + -18, 147, 271,-32766,-32766, 277, 697, 700, 881,-32766, + 411, 890, 893, 146, 682, 282, 881, 907,-32766, 281, + 513, 514, 286, 1212, 1213, 1214, 1215, 1209, 1210, 326, + 131, 145, 939, 287, 682, 1216, 1211, 109, 270,-32766, + 798, 807,-32766, 662, 639, 1191, 657, 72, 675, 1075, + 317, 320,-32766,-32766,-32766, 1305,-32766, 301,-32766, 628, + -32766, 431, 543,-32766,-32766, 923, 555, 924,-32766,-32766, + -32766, 1229, 549,-32766,-32766,-32766, -4, 891, -490, 1191, + -32766, 411, 644, 893, 299, 682,-32766,-32766,-32766,-32766, + -32766, 893,-32766, 682,-32766, 13, 1231,-32766, 452, 480, + 645, 909,-32766,-32766,-32766,-32766, 658, -480,-32766,-32766, + 0, 1191, 0, 0,-32766, 411, 0, 298,-32766,-32766, + -32766, 305,-32766,-32766,-32766, 0,-32766, 0, 806,-32766, + 0, 0, 0, 475,-32766,-32766,-32766,-32766, 0, 7, + -32766,-32766, 16, 1191, 561, 596,-32766, 411, 1219, 891, + -32766,-32766,-32766, 362,-32766,-32766,-32766, 818,-32766, -267, + 881,-32766, 39, 293, 0, 0,-32766,-32766,-32766, 40, + 705, 706,-32766,-32766, 872, 963, 940, 947,-32766, 411, + 937, 948, 365, 870, 427, 891, 935,-32766, 1049, 291, + 1244, 1052, 1053, -111, -111, 1050, 1051, 1057, -560, 1262, + 1296, 633, 0, 826, -111, -111, -111, -111, 33, 315, + -32766, 361, 683, 686, 690, 692, 1191, 693, 694, 695, + 699, 685, 320,-32766,-32766,-32766, 9,-32766, 702,-32766, + 868,-32766, 881, 1300,-32766, 893, 1302, 682, -4,-32766, + -32766,-32766, 829, 828, 837,-32766,-32766, 916, -242, -242, + -242,-32766, 411, 955, 365, 27, 836, 1301, 915, 917, + -32766, 914, 1177, 900, 910, -111, -111, 807, 881, 898, + 945, 1222, 946, 1299, 1256, 867, -111, -111, -111, -111, + 1245, 1263, 1269, 1272, -241, -241, -241, -558, -532, -531, + 365, -530, 1, 28, 29, 38, 42, 46, 71, 0, + 75, -111, -111, 76, 77, 78, 79, 893, 80, 682, + -242, 867, -111, -111, -111, -111, 142, 152, 156, 245, + 322, 347, 514, 348, 1212, 1213, 1214, 1215, 1209, 1210, + 349, 350, 351, 352, 353, 354, 1216, 1211, 355, 356, + 357, 359, 428, 893, -265, 682, -241, -264, 72, 0, + 18, 317, 320, 19, 20, 21, 23, 398, 471, 472, + 479, 482, 483, 484, 485, 489, 490, 491, 498, 669, + 1202, 1145, 1220, 1019, 1018, 1181, -269, -103, 17, 22, + 26, 290, 397, 589, 593, 620, 674, 1149, 1197, 1146, + 1275, 0, -494, 1162, 0, 1223 ); protected $actionCheck = array( 2, 3, 4, 5, 6, 7, 0, 9, 10, 11, - 12, 13, 119, 120, 121, 122, 9, 10, 11, 44, + 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, 116, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 117, 118, 1, 8, 57, 9, 10, 11, 137, - 138, 31, 128, 129, 130, 131, 106, 107, 31, 71, + 43, 117, 118, 9, 10, 57, 9, 10, 11, 137, + 138, 155, 128, 129, 130, 131, 106, 107, 8, 71, 72, 73, 74, 75, 76, 77, 116, 30, 80, 32, - 33, 34, 35, 36, 8, 87, 88, 89, 90, 91, + 33, 34, 35, 36, 1, 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, 1, 80, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 8, 1, 85, 101, 80, 150, 151, + 132, 133, 30, 80, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 51, 1, 161, 101, 80, 150, 151, 152, 8, 154, 9, 10, 11, 2, 3, 4, 5, 6, 7, 164, 9, 10, 11, 12, 13, 123, 9, - 10, 11, 82, 31, 30, 85, 32, 33, 34, 35, + 10, 11, 80, 161, 30, 83, 32, 33, 34, 35, 36, 37, 38, 116, 117, 118, 119, 120, 121, 122, - 30, 37, 38, 9, 10, 11, 1, 14, 161, 9, - 10, 11, 9, 10, 11, 1, 146, 14, 155, 156, - 157, 57, 1, 161, 30, 162, 32, 33, 34, 35, - 30, 8, 32, 33, 34, 71, 72, 73, 74, 75, - 76, 77, 1, 31, 80, 31, 8, 147, 148, 97, - 164, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 30, 37, 38, 106, 107, 1, 9, 10, 11, 1, + 53, 54, 55, 116, 57, 1, 8, 14, 155, 156, + 157, 57, 9, 10, 11, 162, 69, 30, 116, 32, + 33, 119, 120, 121, 122, 71, 72, 73, 74, 75, + 76, 77, 8, 30, 80, 32, 33, 34, 35, 137, + 138, 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, 84, 1, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 164, + 126, 127, 128, 129, 130, 131, 132, 133, 84, 70, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 9, 9, 10, 11, 160, 150, 151, 152, 164, 154, 2, - 3, 4, 5, 6, 7, 84, 9, 10, 11, 12, + 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, 164, 57, 9, - 9, 10, 11, 53, 54, 55, 161, 57, 8, 1, - 69, 159, 167, 159, 57, 161, 106, 107, 8, 69, - 159, 30, 1, 32, 33, 14, 116, 164, 71, 72, - 73, 74, 75, 76, 77, 97, 1, 80, 30, 70, - 159, 70, 161, 14, 87, 88, 89, 90, 91, 92, + 49, 50, 51, 52, 53, 54, 55, 116, 57, 14, + 9, 10, 11, 134, 135, 161, 8, 164, 160, 1, + 69, 167, 164, 159, 57, 161, 80, 8, 137, 138, + 1, 30, 1, 32, 33, 34, 1, 14, 71, 72, + 73, 74, 75, 76, 77, 31, 1, 80, 30, 70, + 30, 9, 10, 11, 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, 9, 10, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 8, 134, 135, 134, 135, 150, 151, 152, - 2, 3, 4, 5, 6, 7, 80, 82, 149, 51, - 12, 13, 101, 15, 116, 37, 38, 106, 80, 108, - 161, 8, 163, 116, 113, 75, 76, 116, 117, 118, - 119, 120, 121, 122, 123, 137, 138, 8, 80, 1, - 106, 83, 108, 80, 137, 138, 8, 8, 50, 51, - 9, 10, 11, 128, 56, 1, 58, 59, 60, 61, + 133, 8, 156, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 8, 134, 135, 8, 8, 150, 151, 152, + 2, 3, 4, 5, 6, 7, 97, 82, 149, 31, + 12, 13, 101, 15, 116, 8, 116, 106, 80, 108, + 161, 85, 163, 106, 113, 108, 8, 116, 117, 118, + 119, 120, 121, 122, 123, 137, 138, 137, 138, 14, + 9, 10, 11, 80, 82, 14, 8, 85, 50, 51, + 50, 51, 52, 128, 56, 1, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 70, 71, - 72, 73, 74, 162, 75, 76, 78, 79, 80, 116, - 82, 1, 156, 158, 86, 87, 88, 89, 163, 91, - 8, 93, 167, 95, 156, 8, 98, 99, 106, 161, - 108, 103, 104, 105, 106, 107, 1, 109, 110, 101, - 102, 31, 160, 115, 116, 8, 164, 1, 155, 156, - 157, 70, 124, 125, 126, 8, 70, 1, 70, 106, - 107, 134, 135, 8, 136, 137, 82, 139, 140, 141, - 142, 143, 144, 145, 1, 8, 149, 155, 14, 151, - 152, 8, 8, 155, 156, 157, 158, 1, 161, 8, + 72, 73, 74, 162, 159, 97, 78, 79, 80, 116, + 82, 1, 146, 158, 86, 87, 88, 89, 163, 91, + 31, 93, 167, 95, 156, 14, 98, 99, 35, 161, + 37, 103, 104, 105, 106, 107, 1, 109, 110, 147, + 148, 31, 160, 115, 116, 8, 164, 1, 155, 156, + 157, 70, 124, 125, 126, 8, 70, 1, 70, 37, + 38, 134, 135, 8, 136, 137, 82, 139, 140, 141, + 142, 143, 144, 145, 8, 35, 149, 37, 164, 151, + 152, 164, 164, 155, 156, 157, 158, 1, 161, 8, 163, 163, 82, 165, 166, 167, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 75, 76, 77, 106, 107, 134, 135, 31, 8, 84, + 75, 76, 77, 75, 76, 134, 135, 31, 8, 84, 134, 135, 134, 135, 1, 90, 8, 92, 82, 94, - 149, 96, 37, 38, 14, 149, 80, 149, 128, 59, - 60, 106, 161, 14, 1, 161, 106, 161, 108, 161, - 70, 167, 117, 118, 31, 14, 30, 70, 50, 51, - 52, 14, 127, 128, 129, 130, 131, 70, 158, 74, - 84, 111, 112, 163, 31, 80, 106, 167, 108, 159, - 31, 161, 87, 88, 89, 16, 91, 16, 93, 16, + 149, 96, 37, 38, 8, 149, 80, 149, 128, 59, + 60, 106, 161, 8, 1, 161, 8, 161, 159, 161, + 70, 167, 117, 118, 31, 8, 106, 70, 108, 106, + 14, 108, 127, 128, 129, 130, 131, 70, 158, 74, + 84, 75, 76, 163, 31, 80, 159, 167, 161, 101, + 102, 14, 87, 88, 89, 14, 91, 31, 93, 16, 95, 37, 38, 98, 159, 1, 161, 162, 103, 104, - 105, 37, 38, 16, 109, 110, 16, 84, 16, 163, - 115, 116, 16, 167, 134, 135, 16, 161, 16, 124, - 31, 134, 135, 167, 70, 31, 31, 84, 31, 149, - 31, 134, 135, 160, 31, 31, 82, 164, 74, 31, - 86, 161, 116, 31, 80, 159, 31, 161, 161, 154, + 105, 37, 38, 1, 109, 110, 16, 84, 16, 163, + 115, 116, 16, 167, 134, 135, 16, 161, 31, 124, + 16, 134, 135, 167, 70, 31, 16, 84, 16, 149, + 16, 134, 135, 31, 106, 107, 82, 31, 74, 31, + 86, 161, 106, 107, 80, 159, 31, 161, 161, 154, 31, 87, 88, 89, 31, 91, 31, 93, 161, 95, - 31, 31, 98, 137, 138, 31, 31, 103, 104, 105, - 31, 31, 31, 109, 110, 38, 69, 35, 84, 115, - 116, 35, 159, 35, 161, 35, 35, 70, 124, 57, - 136, 137, 82, 139, 140, 141, 142, 143, 144, 77, - 31, 80, 159, 83, 161, 151, 152, 89, 82, 74, - 94, 97, 85, 85, 90, 80, 128, 163, 113, 128, - 166, 167, 87, 88, 89, 92, 91, 96, 93, 116, - 95, 133, 146, 98, 128, 97, 100, 153, 103, 104, - 105, 97, 149, 74, 109, 110, 0, 1, 163, 80, - 115, 116, 100, 159, 153, 161, 87, 88, 89, 124, - 91, 114, 93, 154, 95, -1, 155, 98, -1, -1, - -1, -1, 103, 104, 105, 74, -1, 132, 109, 110, - -1, 80, -1, -1, 115, 116, 132, -1, 87, 88, - 89, -1, 91, 124, 93, 146, 95, -1, -1, 98, - -1, 158, 149, 102, 103, 104, 105, 74, 149, 149, - 109, 110, 149, 80, 81, 159, 115, 116, 160, 1, - 87, 88, 89, 159, 91, 124, 93, 159, 95, 159, - 84, 98, 159, 159, 159, 159, 103, 104, 105, 159, + 111, 112, 98, 31, 31, 31, 31, 103, 104, 105, + 31, 31, 31, 109, 110, 31, 31, 31, 84, 115, + 116, 31, 159, 31, 161, 37, 84, 38, 124, 35, + 136, 137, 35, 139, 140, 141, 142, 143, 144, 35, + 31, 70, 159, 37, 161, 151, 152, 69, 57, 74, + 80, 82, 85, 77, 90, 80, 94, 163, 92, 82, + 166, 167, 87, 88, 89, 83, 91, 114, 93, 113, + 95, 128, 85, 98, 116, 128, 153, 128, 103, 104, + 105, 146, 89, 74, 109, 110, 0, 1, 149, 80, + 115, 116, 96, 159, 133, 161, 87, 88, 89, 124, + 91, 159, 93, 161, 95, 97, 146, 98, 97, 97, + 100, 154, 103, 104, 105, 74, 100, 149, 109, 110, + -1, 80, -1, -1, 115, 116, -1, 132, 87, 88, + 89, 132, 91, 124, 93, -1, 95, -1, 155, 98, + -1, -1, -1, 102, 103, 104, 105, 74, -1, 149, + 109, 110, 149, 80, 81, 153, 115, 116, 160, 1, + 87, 88, 89, 149, 91, 124, 93, 160, 95, 164, + 84, 98, 159, 158, -1, -1, 103, 104, 105, 159, 159, 159, 109, 110, 159, 159, 159, 159, 115, 116, - 159, 159, 106, 159, 108, 1, 160, 124, 160, 113, - 160, 162, 160, 117, 118, 160, 162, 161, 161, 161, - 161, 161, 161, 127, 128, 129, 130, 131, 161, 161, - 74, 161, 161, 161, 161, 166, 80, 162, 162, 162, - 162, 162, 162, 87, 88, 89, 150, 91, 162, 93, + 159, 159, 106, 159, 108, 1, 159, 124, 159, 113, + 160, 159, 159, 117, 118, 159, 159, 159, 163, 160, + 160, 160, -1, 127, 128, 129, 130, 131, 161, 161, + 74, 161, 161, 161, 161, 161, 80, 161, 161, 161, + 161, 161, 167, 87, 88, 89, 150, 91, 162, 93, 162, 95, 84, 162, 98, 159, 162, 161, 162, 103, 104, 105, 162, 162, 162, 109, 110, 162, 100, 101, 102, 115, 116, 162, 106, 70, 162, 162, 162, 162, 124, 162, 162, 162, 162, 117, 118, 82, 84, 162, - 164, 86, 163, 163, 163, 127, 128, 129, 130, 131, - 163, 163, 163, 163, 100, 101, 102, 163, 163, 163, + 162, 86, 162, 162, 162, 127, 128, 129, 130, 131, + 162, 162, 162, 162, 100, 101, 102, 163, 163, 163, 106, 163, 163, 163, 163, 163, 163, 163, 163, -1, 163, 117, 118, 163, 163, 163, 163, 159, 163, 161, 162, 127, 128, 129, 130, 131, 163, 163, 163, 163, 163, 163, 137, 163, 139, 140, 141, 142, 143, 144, - 163, 163, 163, 163, -1, 164, 151, 152, 164, 164, - 164, 164, 164, 159, 164, 161, 162, 164, 163, 167, + 163, 163, 163, 163, 163, 163, 151, 152, 163, 163, + 163, 163, 163, 159, 164, 161, 162, 164, 163, -1, 164, 166, 167, 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, 164, - 164, 164, 164, 164, -1, 165, 165 + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, -1, 165, 165, -1, 166 ); protected $actionBase = array( 0, -2, 154, 565, 876, 948, 984, 514, 53, 398, - 822, 307, 307, 67, 307, 307, 616, 673, 673, 724, - 673, 204, 653, 231, 231, 231, 625, 625, 625, 625, - 694, 694, 831, 831, 863, 799, 765, 936, 936, 936, + 837, 307, 307, 67, 307, 307, 307, 653, 724, 724, + 732, 724, 616, 673, 204, 204, 204, 625, 625, 625, + 625, 694, 694, 831, 831, 863, 799, 765, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, @@ -504,62 +506,63 @@ class Php7 extends \PhpParser\ParserAbstract 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, - 211, 202, 288, 677, 1010, 1016, 1012, 1017, 1008, 1007, - 1011, 1013, 1018, 897, 899, 771, 900, 901, 902, 907, - 1014, 835, 1009, 1015, 291, 291, 291, 291, 291, 291, + 936, 936, 375, 519, 369, 701, 1017, 1023, 1019, 1024, + 1015, 1014, 1018, 1020, 1025, 911, 912, 782, 918, 919, + 920, 921, 1021, 841, 1016, 1022, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, - 340, 193, 432, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, - 501, 501, 501, 160, 160, 160, 341, 684, 684, 190, - 184, 610, 47, 985, 985, 985, 985, 985, 985, 985, - 985, 985, 985, 144, 144, 7, 7, 7, 7, 7, - 371, -25, -25, -25, -25, 540, 385, 576, 358, 45, - 394, 638, 638, 656, 656, 367, 367, 367, 367, -78, - -78, -78, -66, 319, 457, 452, 60, 423, 586, 586, - 586, 586, 423, 423, 423, 423, 779, 849, 423, 423, - 423, 511, 516, 516, 518, 300, 300, 300, 516, 600, - 758, 90, 600, 90, 195, 418, 743, -40, 260, 412, - -107, 743, 617, 627, 603, 143, 741, 483, 741, 1006, - 757, 749, 719, 824, 853, 1019, 766, 895, 782, 896, - 321, 679, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - 1005, 1005, 1005, 982, 438, 1006, 386, 982, 982, 982, - 438, 438, 438, 438, 438, 438, 438, 438, 438, 438, - 590, 386, 410, 459, 386, 781, 438, 211, 783, 211, - 211, 211, 211, 943, 211, 211, 211, 211, 211, 211, - 956, 753, 37, 211, 202, 52, 52, 550, 131, 52, - 52, 52, 52, 211, 211, 211, 483, 762, 714, 537, - 731, 213, 762, 762, 762, 142, 76, 183, 135, 570, - 751, 751, 756, 918, 918, 751, 740, 751, 756, 926, - 751, 918, 773, 350, 597, 542, 577, 604, 918, 473, - 751, 751, 751, 751, 611, 751, 444, 360, 751, 751, - 775, 760, 784, 46, 918, 918, 918, 784, 567, 728, - 728, 728, 798, 800, 735, 759, 499, 489, 648, 314, - 767, 759, 759, 751, 585, 735, 759, 735, 759, 739, - 759, 759, 759, 735, 759, 751, 740, 547, 759, 722, - 640, 228, 759, 6, 928, 929, 30, 930, 924, 931, - 970, 932, 933, 839, 941, 925, 934, 920, 919, 770, - 699, 701, 789, 723, 917, 737, 737, 737, 910, 737, - 737, 737, 737, 737, 737, 737, 737, 699, 788, 793, - 718, 748, 945, 703, 717, 716, 834, 1020, 1021, 721, - 736, 943, 1000, 935, 786, 720, 980, 953, 829, 837, - 954, 955, 983, 1001, 1002, 855, 747, 856, 857, 826, - 957, 840, 737, 928, 933, 925, 934, 920, 919, 745, - 742, 734, 738, 733, 729, 725, 727, 755, 909, 715, - 828, 956, 911, 699, 830, 975, 836, 986, 989, 838, - 768, 750, 832, 858, 958, 960, 967, 841, 1003, 794, - 976, 906, 990, 774, 859, 991, 992, 993, 994, 860, - 847, 848, 850, 803, 754, 971, 761, 866, 361, 778, - 780, 969, 379, 942, 851, 868, 871, 995, 996, 997, - 874, 937, 804, 977, 746, 978, 974, 805, 806, 594, - 772, 776, 650, 659, 880, 881, 882, 940, 764, 752, - 810, 811, 1004, 885, 671, 812, 726, 891, 999, 730, - 732, 763, 852, 790, 777, 744, 968, 769, 815, 894, - 816, 817, 818, 998, 821, 0, 0, 0, 0, 0, + 291, 291, 290, 491, 44, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 160, 160, 160, 187, 684, + 684, 341, 203, 610, 47, 985, 985, 985, 985, 985, + 985, 985, 985, 985, 985, 144, 144, 7, 7, 7, + 7, 7, 371, -25, -25, -25, -25, 540, 385, 102, + 576, 358, 45, 377, 460, 460, 360, 231, 231, 231, + 231, 231, 231, -78, -78, -78, -78, -78, -66, 319, + 457, -94, 396, 423, 586, 586, 586, 586, 423, 423, + 423, 423, 750, 1029, 423, 423, 423, 511, 516, 516, + 518, 147, 147, 147, 516, 583, 777, 422, 583, 422, + 194, 92, 748, -40, 87, 412, 748, 617, 627, 198, + 143, 773, 658, 773, 1013, 757, 764, 717, 838, 860, + 1026, 800, 908, 806, 910, 219, 686, 1012, 1012, 1012, + 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 855, 552, + 1013, 286, 855, 855, 855, 552, 552, 552, 552, 552, + 552, 552, 552, 552, 552, 679, 286, 568, 626, 286, + 794, 552, 375, 758, 375, 375, 375, 375, 958, 375, + 375, 375, 375, 375, 375, 970, 769, -16, 375, 519, + 12, 12, 547, 83, 12, 12, 12, 12, 375, 375, + 375, 658, 781, 713, 666, 792, 448, 781, 781, 781, + 438, 444, 193, 447, 570, 523, 580, 760, 760, 767, + 929, 929, 760, 759, 760, 767, 934, 760, 929, 805, + 359, 648, 577, 611, 656, 929, 478, 760, 760, 760, + 760, 665, 760, 467, 433, 760, 760, 785, 774, 789, + 60, 929, 929, 929, 789, 596, 751, 751, 751, 811, + 812, 746, 771, 567, 498, 677, 348, 779, 771, 771, + 760, 640, 746, 771, 746, 771, 747, 771, 771, 771, + 746, 771, 759, 585, 771, 734, 668, 224, 771, 6, + 935, 937, 354, 940, 932, 941, 979, 942, 943, 851, + 956, 933, 945, 931, 930, 780, 703, 720, 790, 729, + 928, 768, 768, 768, 925, 768, 768, 768, 768, 768, + 768, 768, 768, 703, 788, 804, 733, 783, 960, 722, + 726, 725, 868, 1027, 1028, 737, 739, 958, 1006, 953, + 803, 730, 992, 967, 866, 848, 968, 969, 993, 1007, + 1008, 871, 761, 874, 880, 797, 971, 852, 768, 935, + 943, 933, 945, 931, 930, 763, 762, 753, 755, 749, + 745, 736, 738, 770, 1009, 924, 835, 830, 970, 926, + 703, 839, 986, 847, 994, 995, 850, 801, 772, 840, + 881, 972, 975, 976, 853, 1010, 810, 989, 795, 996, + 802, 882, 997, 998, 999, 1000, 885, 854, 856, 857, + 815, 754, 980, 786, 891, 335, 787, 796, 978, 363, + 957, 858, 894, 895, 1001, 1002, 1003, 896, 954, 816, + 990, 752, 991, 983, 817, 818, 485, 784, 778, 541, + 676, 897, 899, 900, 955, 775, 766, 821, 822, 1011, + 901, 697, 824, 740, 902, 1005, 742, 744, 756, 859, + 793, 743, 798, 977, 776, 827, 907, 829, 832, 833, + 1004, 836, 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, 0, 458, 458, 458, 458, 458, 458, 307, - 307, 307, 307, 0, 0, 307, 0, 0, 458, 458, + 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, @@ -584,163 +587,160 @@ class Php7 extends \PhpParser\ParserAbstract 291, 291, 291, 291, 291, 291, 291, 291, 291, 423, 423, 291, 291, 0, 291, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 291, 291, 291, 291, 291, - 291, 291, 773, 300, 300, 300, 300, 423, 423, 423, - 423, -88, -88, 300, 300, 423, 423, 423, 423, 423, - 423, 423, 423, 423, 0, 0, 0, 386, 90, 0, - 740, 740, 740, 740, 0, 0, 0, 0, 90, 90, + 291, 291, 805, 147, 147, 147, 147, 423, 423, 423, + 423, 423, -88, -88, 147, 147, 423, 423, 423, 423, + 423, 423, 423, 423, 423, 423, 423, 423, 0, 0, + 0, 286, 422, 0, 759, 759, 759, 759, 0, 0, + 0, 0, 422, 422, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 286, 422, 0, 286, 0, + 759, 759, 423, 805, 805, 314, 423, 0, 0, 0, + 0, 286, 759, 286, 552, 422, 552, 552, 12, 375, + 314, 608, 608, 608, 608, 0, 658, 805, 805, 805, + 805, 805, 805, 805, 805, 805, 805, 805, 759, 0, + 805, 0, 759, 759, 759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 386, 90, 0, 386, 0, 740, 740, 423, 773, - 773, 498, 0, 423, 0, 0, 0, 0, 386, 740, - 386, 438, 90, 438, 438, 52, 211, 498, 468, 468, - 468, 468, 0, 483, 773, 773, 773, 773, 773, 773, - 773, 773, 773, 773, 773, 740, 0, 773, 0, 740, - 740, 740, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 740, 0, 0, - 918, 0, 0, 0, 0, 751, 0, 0, 0, 0, - 0, 0, 751, 926, 0, 0, 0, 0, 0, 0, - 740, 0, 0, 0, 0, 0, 0, 0, 0, 737, - 768, 0, 768, 0, 737, 737, 737 + 759, 0, 0, 929, 0, 0, 0, 0, 760, 0, + 0, 0, 0, 0, 0, 760, 934, 0, 0, 0, + 0, 0, 0, 759, 0, 0, 0, 0, 0, 0, + 0, 0, 768, 801, 0, 801, 0, 768, 768, 768 ); 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, 569, 569, 569, 569, - 32767,32767, 246, 103,32767,32767, 445, 363, 363, 363, - 32767,32767, 513, 513, 513, 513, 513, 513,32767,32767, - 32767,32767,32767,32767, 445,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 578, 578, 578, + 578,32767,32767, 246, 103,32767,32767, 454, 372, 372, + 372,32767,32767, 522, 522, 522, 522, 522, 522,32767, + 32767,32767,32767,32767,32767, 454,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,32767,32767, - 32767,32767,32767, 103,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, 310, + 32767,32767,32767,32767, 103,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767, 562,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767, 571,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767, 449, 428, 429, 431, 432, 362, - 514, 568, 304, 565, 361, 146, 316, 306, 234, 307, - 250, 450, 251, 451, 454, 455, 211, 278, 358, 150, - 392, 446, 394, 444, 448, 393, 368, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, - 366, 367, 447, 425, 424, 423, 390,32767,32767, 391, - 395, 365, 398,32767,32767,32767,32767,32767,32767,32767, - 32767, 103,32767, 396, 397, 414, 415, 412, 413, 416, - 32767, 417, 418, 419, 420,32767,32767,32767,32767, 342, - 340, 405, 406, 295, 295,32767,32767,32767,32767,32767, - 32767,32767,32767, 507, 422,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767, 103,32767, - 101, 509, 387, 389, 477, 400, 401, 399, 369,32767, - 484,32767, 103, 486,32767,32767,32767, 112,32767,32767, - 272,32767, 508,32767, 515, 515,32767, 470, 101, 194, - 32767, 194, 194,32767,32767,32767,32767,32767,32767,32767, - 576, 470, 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, 260, 262, 103, 530, 194,32767, 489,32767, + 32767,32767,32767,32767,32767,32767, 458, 437, 438, 440, + 441, 371, 523, 577, 313, 574, 370, 146, 325, 315, + 234, 316, 250, 459, 251, 460, 463, 464, 211, 279, + 367, 150, 401, 455, 403, 453, 457, 402, 377, 382, + 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, + 393, 394, 375, 376, 456, 434, 433, 432, 399,32767, + 32767, 400, 404, 374, 407,32767,32767,32767,32767,32767, + 32767,32767,32767, 103,32767, 405, 406, 423, 424, 421, + 422, 425,32767, 426, 427, 428, 429,32767,32767, 302, + 32767,32767, 351, 349, 414, 415, 302,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 516, + 431,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 103,32767, 101, 518, 396, 398, + 486, 409, 410, 408, 378,32767, 493,32767, 103, 495, + 32767,32767,32767, 112,32767,32767,32767, 517,32767, 524, + 524,32767, 479, 101, 194,32767, 194, 194,32767,32767, + 32767,32767,32767,32767,32767, 585, 479, 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, 260, 262, 103, + 539, 194,32767, 498,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767, 491,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767, 482,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767, 470, 410, 139,32767, - 139, 515, 402, 403, 404, 472, 515, 515, 515,32767, - 32767,32767,32767, 487, 487, 101, 101, 101, 101, 482, - 32767,32767, 112, 100, 100, 100, 100, 100, 104, 102, - 32767,32767,32767,32767, 100,32767, 102, 102,32767,32767, - 217, 208, 215, 102,32767, 534, 535, 215, 102, 219, - 219, 219, 239, 239, 461, 297, 102, 100, 102, 102, - 196, 297, 297,32767, 102, 461, 297, 461, 297, 198, - 297, 297, 297, 461, 297,32767,32767, 102, 297, 210, - 100, 100, 297,32767,32767,32767, 472,32767,32767,32767, + 32767, 479, 419, 139,32767, 139, 524, 411, 412, 413, + 481, 524, 524, 524, 298, 281,32767,32767,32767,32767, + 496, 496, 101, 101, 101, 101, 491,32767,32767, 112, + 100, 100, 100, 100, 100, 104, 102,32767,32767,32767, + 32767, 100,32767, 102, 102,32767,32767, 217, 208, 215, + 102,32767, 543, 544, 215, 102, 219, 219, 219, 239, + 239, 470, 304, 102, 100, 102, 102, 196, 304, 304, + 32767, 102, 470, 304, 470, 304, 198, 304, 304, 304, + 470, 304,32767, 102, 304, 210, 100, 100, 304,32767, + 32767,32767, 481,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 511,32767, 528, + 541, 417, 418, 420, 526, 442, 443, 444, 445, 446, + 447, 448, 450, 573,32767, 485,32767,32767,32767,32767, + 324, 583,32767, 583,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767, 502,32767, 519, 532, 408, 409, 411, 517, 433, - 434, 435, 436, 437, 438, 439, 441, 564,32767, 476, - 32767,32767,32767,32767, 315, 574,32767, 574,32767,32767, + 32767, 584,32767, 524,32767,32767,32767,32767, 416, 9, + 76, 43, 44, 52, 58, 502, 503, 504, 505, 499, + 500, 506, 501,32767,32767, 507, 549,32767,32767, 525, + 576,32767,32767,32767,32767,32767,32767, 139,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 511,32767, + 137,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767, 524,32767,32767,32767, 300, 301,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767, 575,32767, 515,32767,32767, - 32767,32767, 407, 9, 76, 43, 44, 52, 58, 493, - 494, 495, 496, 490, 491, 497, 492,32767, 498, 540, - 32767,32767, 516, 567,32767,32767,32767,32767,32767,32767, - 139,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767, 502,32767, 137,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767, 515,32767,32767,32767, 292, - 294,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767, 515,32767,32767,32767, - 280, 282,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767, 277,32767,32767, 357, - 32767,32767,32767,32767, 336,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767, 152, 152, 3, 3, 318, - 152, 152, 152, 318, 152, 318, 318, 318, 152, 152, - 152, 152, 152, 152, 184, 254, 257, 239, 239, 152, - 328, 152 + 32767,32767,32767, 524,32767,32767,32767, 283, 284,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767, 278,32767,32767, 366,32767,32767,32767, + 32767, 345,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767, 152, 152, 3, 3, 327, 152, 152, 152, + 327, 152, 327, 327, 327, 152, 152, 152, 152, 152, + 152, 272, 184, 254, 257, 239, 239, 152, 337, 152 ); protected $goto = array( - 192, 192, 663, 417, 636, 911, 983, 990, 991, 411, - 302, 303, 324, 557, 308, 416, 325, 418, 615, 1005, - 671, 317, 317, 317, 317, 163, 163, 163, 163, 216, - 193, 189, 189, 173, 175, 211, 189, 189, 189, 189, - 189, 190, 190, 190, 190, 190, 190, 184, 185, 186, - 187, 188, 213, 211, 214, 515, 516, 407, 517, 519, - 520, 521, 522, 523, 524, 525, 526, 1074, 164, 165, - 166, 191, 167, 168, 169, 162, 170, 171, 172, 174, - 210, 212, 215, 233, 236, 239, 240, 242, 253, 254, - 255, 256, 257, 258, 259, 261, 262, 263, 264, 271, - 272, 305, 306, 307, 412, 413, 414, 562, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 176, 232, 177, 194, 195, 196, 234, - 184, 185, 186, 187, 188, 213, 1074, 197, 178, 179, - 180, 198, 194, 181, 235, 199, 161, 200, 201, 182, - 202, 203, 204, 183, 205, 206, 207, 208, 209, 819, - 579, 601, 601, 541, 532, 815, 816, 1204, 1204, 1204, - 1204, 1204, 1204, 1204, 1204, 1204, 1204, 954, 928, 928, - 926, 928, 695, 817, 531, 963, 958, 381, 385, 542, - 580, 584, 383, 532, 541, 550, 551, 390, 560, 581, - 595, 596, 824, 793, 872, 867, 868, 881, 14, 825, - 869, 822, 870, 871, 823, 480, 850, 481, 875, 527, - 527, 527, 527, 488, 583, 1222, 1222, 791, 1026, 1022, - 1023, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, - 1222, 1220, 1220, 812, 812, 599, 633, 1220, 1220, 1220, - 1220, 1220, 1220, 1220, 1220, 1220, 1220, 313, 297, 1173, - 1173, 1173, 987, 282, 282, 282, 282, 987, 987, 987, - 987, 987, 987, 987, 987, 987, 447, 447, 432, 249, - 249, 1173, 554, 432, 432, 447, 1173, 1173, 1173, 1173, - 1046, 1047, 1173, 1173, 1173, 1254, 1254, 1254, 1254, 337, - 797, 1272, 1272, 930, 246, 246, 246, 246, 248, 250, - 888, 335, 876, 340, 877, 889, 1249, 1250, 1272, 518, - 518, 832, 1262, 340, 340, 518, 518, 518, 518, 518, - 518, 518, 518, 518, 518, 1275, 844, 340, 340, 831, - 340, 797, 1289, 797, 630, 1169, 644, 645, 646, 529, - 529, 529, 611, 612, 534, 1273, 1273, 340, 812, 951, - 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, - 432, 438, 1273, 432, 558, 593, 924, 924, 924, 924, - 379, 635, 438, 918, 925, 553, 1123, 1154, 904, 422, - 547, 1155, 1158, 905, 1159, 548, 326, 594, 1170, 696, - 614, 616, 1233, 634, 410, 807, 590, 653, 657, 965, - 661, 669, 961, 456, 1247, 1248, 809, 837, 1244, 1244, - 1244, 1171, 1230, 1231, 5, 656, 6, 533, 545, 389, - 968, 968, 533, 1166, 545, 834, 973, 382, 922, 397, - 670, 1256, 1256, 1256, 1256, 1011, 699, 561, 450, 451, - 452, 846, 842, 534, 457, 1280, 1281, 619, 619, 1015, - 1057, 395, 396, 995, 992, 993, 642, 1240, 643, 935, - 399, 400, 401, 461, 654, 0, 0, 0, 402, 0, - 840, 0, 333, 578, 1039, 0, 674, 660, 660, 0, - 666, 1037, 489, 588, 602, 605, 606, 607, 608, 627, - 628, 629, 673, 0, 0, 0, 1013, 893, 1062, 0, - 1242, 1242, 1013, 1168, 598, 252, 252, 0, 0, 970, - 269, 845, 833, 1010, 1014, 530, 530, 836, 0, 639, - 949, 933, 0, 338, 339, 830, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1165, 0, - 0, 0, 0, 0, 923, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1055, 849 + 194, 194, 670, 422, 643, 463, 1264, 1265, 1022, 416, + 308, 309, 329, 563, 314, 421, 330, 423, 622, 801, + 678, 637, 586, 651, 652, 653, 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, 521, 522, 412, 523, + 525, 526, 527, 528, 529, 530, 531, 532, 1091, 166, + 167, 168, 193, 169, 170, 171, 164, 172, 173, 174, + 176, 212, 214, 217, 235, 238, 241, 242, 244, 255, + 256, 257, 258, 259, 260, 261, 263, 264, 265, 266, + 274, 275, 311, 312, 313, 417, 418, 419, 568, 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, 1091, 199, 180, + 181, 182, 200, 196, 183, 237, 201, 199, 163, 202, + 203, 184, 204, 205, 206, 185, 207, 208, 209, 210, + 211, 323, 323, 323, 323, 827, 608, 608, 824, 547, + 538, 342, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, + 1221, 1221, 1239, 1239, 288, 288, 288, 288, 1239, 1239, + 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 388, 538, + 547, 556, 557, 395, 566, 588, 602, 603, 832, 825, + 880, 875, 876, 889, 15, 833, 877, 830, 878, 879, + 831, 799, 251, 251, 883, 919, 992, 1000, 1004, 1001, + 1005, 1237, 1237, 938, 1043, 1039, 1040, 1237, 1237, 1237, + 1237, 1237, 1237, 1237, 1237, 1237, 1237, 858, 248, 248, + 248, 248, 250, 252, 533, 533, 533, 533, 487, 590, + 488, 1190, 1190, 997, 1190, 997, 494, 1290, 1290, 560, + 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, + 997, 997, 1261, 1261, 1290, 1261, 340, 1190, 930, 402, + 677, 1279, 1190, 1190, 1190, 1190, 959, 345, 1190, 1190, + 1190, 1271, 1271, 1271, 1271, 606, 640, 345, 345, 1273, + 1273, 1273, 1273, 820, 820, 805, 896, 884, 840, 885, + 897, 345, 345, 5, 345, 6, 1306, 384, 535, 535, + 559, 535, 415, 852, 597, 1257, 839, 540, 524, 524, + 345, 1289, 1289, 642, 524, 524, 524, 524, 524, 524, + 524, 524, 524, 524, 445, 805, 1140, 805, 1289, 932, + 932, 932, 932, 1063, 1064, 445, 926, 933, 386, 390, + 548, 587, 591, 1030, 1292, 331, 554, 1259, 1259, 1030, + 704, 621, 623, 823, 641, 1250, 319, 303, 660, 664, + 973, 668, 676, 969, 429, 553, 962, 936, 936, 934, + 936, 703, 601, 537, 971, 966, 343, 344, 663, 817, + 595, 609, 612, 613, 614, 615, 634, 635, 636, 680, + 439, 1186, 845, 454, 454, 439, 439, 1266, 1267, 820, + 901, 1079, 454, 394, 539, 551, 1183, 605, 540, 539, + 842, 551, 978, 272, 387, 618, 619, 981, 536, 536, + 844, 707, 646, 957, 567, 457, 458, 459, 838, 850, + 254, 254, 1297, 1298, 400, 401, 976, 976, 464, 649, + 1182, 650, 1028, 404, 405, 406, 1187, 661, 424, 1032, + 407, 564, 600, 815, 338, 424, 854, 848, 853, 841, + 1027, 1031, 1009, 1002, 1006, 1003, 1007, 1185, 941, 1188, + 1247, 1248, 943, 0, 1074, 439, 439, 439, 439, 439, + 439, 439, 439, 439, 439, 439, 0, 468, 439, 585, + 1056, 931, 681, 667, 667, 0, 495, 673, 1054, 1171, + 912, 0, 0, 1172, 1175, 913, 1176, 0, 0, 0, + 0, 0, 0, 1072, 857 ); protected $gotoCheck = array( - 42, 42, 72, 65, 65, 87, 87, 87, 87, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 115, - 9, 23, 23, 23, 23, 42, 42, 42, 42, 42, + 42, 42, 72, 65, 65, 166, 166, 166, 119, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 7, + 9, 84, 122, 84, 84, 84, 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, @@ -753,91 +753,88 @@ class Php7 extends \PhpParser\ParserAbstract 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, 15, - 118, 104, 104, 75, 75, 25, 26, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 25, 25, 25, - 25, 25, 25, 27, 25, 25, 25, 58, 58, 58, - 58, 58, 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 15, 7, 15, 15, 15, 15, 75, 15, - 15, 15, 15, 15, 15, 143, 45, 143, 15, 103, - 103, 103, 103, 143, 103, 156, 156, 6, 15, 15, - 15, 156, 156, 156, 156, 156, 156, 156, 156, 156, - 156, 157, 157, 22, 22, 55, 55, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 155, 155, 72, - 72, 72, 72, 24, 24, 24, 24, 72, 72, 72, - 72, 72, 72, 72, 72, 72, 137, 137, 23, 5, - 5, 72, 158, 23, 23, 137, 72, 72, 72, 72, - 132, 132, 72, 72, 72, 9, 9, 9, 9, 93, - 12, 168, 168, 49, 5, 5, 5, 5, 5, 5, - 72, 165, 64, 14, 64, 72, 164, 164, 168, 159, - 159, 35, 167, 14, 14, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 168, 35, 14, 14, 35, - 14, 12, 14, 12, 84, 20, 84, 84, 84, 19, - 19, 19, 83, 83, 14, 169, 169, 14, 22, 99, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 19, 169, 23, 2, 2, 19, 19, 19, 19, - 61, 63, 19, 19, 19, 100, 139, 78, 78, 108, - 9, 78, 78, 78, 78, 48, 29, 9, 20, 48, - 48, 48, 14, 48, 13, 20, 13, 48, 48, 48, - 48, 48, 48, 162, 162, 162, 18, 39, 118, 118, - 118, 20, 20, 20, 46, 14, 46, 9, 9, 28, - 103, 103, 9, 148, 9, 37, 106, 9, 89, 89, - 89, 118, 118, 118, 118, 117, 95, 9, 9, 9, - 9, 41, 9, 14, 145, 9, 9, 111, 111, 120, - 135, 80, 80, 111, 111, 111, 80, 118, 80, 92, - 80, 80, 80, 82, 80, -1, -1, -1, 80, -1, - 9, -1, 80, 8, 8, -1, 8, 8, 8, -1, - 8, 8, 9, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, -1, -1, -1, 118, 17, 17, -1, - 118, 118, 118, 14, 17, 5, 5, -1, -1, 17, - 24, 16, 16, 16, 16, 24, 24, 17, -1, 17, - 17, 16, -1, 93, 93, 17, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, - -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 16, 16 + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 23, 23, 23, 23, 15, 104, 104, 26, 75, + 75, 93, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 160, 160, 24, 24, 24, 24, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 15, 27, + 15, 15, 15, 15, 75, 15, 15, 15, 15, 15, + 15, 6, 5, 5, 15, 87, 87, 87, 87, 87, + 87, 161, 161, 49, 15, 15, 15, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 45, 5, 5, + 5, 5, 5, 5, 103, 103, 103, 103, 147, 103, + 147, 72, 72, 72, 72, 72, 147, 173, 173, 162, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 122, 122, 173, 122, 169, 72, 89, 89, + 89, 171, 72, 72, 72, 72, 99, 14, 72, 72, + 72, 9, 9, 9, 9, 55, 55, 14, 14, 122, + 122, 122, 122, 22, 22, 12, 72, 64, 35, 64, + 72, 14, 14, 46, 14, 46, 14, 61, 19, 19, + 100, 19, 13, 35, 13, 122, 35, 14, 163, 163, + 14, 172, 172, 63, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 19, 12, 143, 12, 172, 19, + 19, 19, 19, 136, 136, 19, 19, 19, 58, 58, + 58, 58, 58, 122, 172, 29, 48, 122, 122, 122, + 48, 48, 48, 25, 48, 14, 159, 159, 48, 48, + 48, 48, 48, 48, 109, 9, 25, 25, 25, 25, + 25, 25, 9, 25, 25, 25, 93, 93, 14, 18, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 23, 20, 39, 141, 141, 23, 23, 168, 168, 22, + 17, 17, 141, 28, 9, 9, 152, 17, 14, 9, + 37, 9, 17, 24, 9, 83, 83, 106, 24, 24, + 17, 95, 17, 17, 9, 9, 9, 9, 17, 9, + 5, 5, 9, 9, 80, 80, 103, 103, 149, 80, + 17, 80, 121, 80, 80, 80, 20, 80, 113, 124, + 80, 2, 2, 20, 80, 113, 41, 9, 16, 16, + 16, 16, 113, 113, 113, 113, 113, 14, 16, 20, + 20, 20, 92, -1, 139, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, -1, 82, 23, 8, + 8, 16, 8, 8, 8, -1, 8, 8, 8, 78, + 78, -1, -1, 78, 78, 78, 78, -1, -1, -1, + -1, -1, -1, 16, 16 ); protected $gotoBase = array( - 0, 0, -303, 0, 0, 278, 214, 194, 476, 7, - 0, 0, 15, 78, 27, -175, 87, 61, 118, 84, - -33, 0, -74, 18, 260, 161, 162, 179, 103, 111, - 0, 0, 0, 0, 0, -35, 0, 107, 0, 105, - 0, 26, -1, 0, 0, 204, -275, 0, -281, 281, - 0, 0, 0, 0, 0, 207, 0, 0, 144, 0, - 0, 340, 0, 143, 294, -234, 0, 0, 0, 0, - 0, 0, -6, 0, 0, -168, 0, 0, -8, 150, - -10, 0, 16, -108, -339, 0, 0, -270, 0, 145, - 0, 0, 42, -164, 0, 52, 0, 0, 0, 326, - 344, 0, 0, 193, -76, 0, 81, 0, 115, 0, - 0, 184, 0, 0, 0, 17, 0, 86, 153, 0, - 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 21, 0, 0, 32, 0, 244, 0, 119, - 0, 0, 0, -260, 0, 30, 0, 0, 79, 0, - 0, 0, 0, 0, 0, -53, -12, 4, 255, 82, - 0, 0, 124, 0, -41, 283, 0, 293, 5, 59, - 0, 0 + 0, 0, -203, 0, 0, 221, 208, 10, 512, 7, + 0, 0, 24, 1, 5, -174, 47, -23, 105, 61, + 38, 0, -10, 158, 181, 379, 164, 205, 102, 84, + 0, 0, 0, 0, 0, -43, 0, 107, 0, 104, + 0, 54, -1, 0, 0, 235, -384, 0, -307, 210, + 0, 0, 0, 0, 0, 266, 0, 0, 324, 0, + 0, 286, 0, 103, 298, -236, 0, 0, 0, 0, + 0, 0, -6, 0, 0, -167, 0, 0, 129, 62, + -14, 0, 53, -22, -669, 0, 0, -52, 0, -11, + 0, 0, 68, -299, 0, 52, 0, 0, 0, 262, + 288, 0, 0, 227, -73, 0, 87, 0, 0, 118, + 0, 0, 0, 209, 0, 0, 0, 0, 0, 6, + 0, 108, 15, 0, 46, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 91, 0, 0, 69, + 0, 390, 0, 86, 0, 0, 0, -224, 0, 37, + 0, 0, 77, 0, 0, 0, 0, 0, 0, 70, + -57, -8, 241, 99, 0, 0, -290, 0, 65, 257, + 0, 261, 39, -35, 0, 0 ); protected $gotoDefault = array( - -32768, 493, 703, 4, 704, 897, 780, 789, 577, 509, - 672, 334, 603, 408, 1238, 874, 1061, 559, 808, 1182, - 1190, 439, 811, 318, 320, 856, 857, 858, 386, 371, - 377, 384, 625, 604, 474, 843, 435, 835, 466, 838, - 434, 847, 160, 405, 491, 851, 3, 853, 536, 884, - 372, 861, 373, 649, 863, 544, 865, 866, 380, 387, - 388, 1066, 552, 600, 878, 241, 546, 879, 370, 880, - 887, 375, 378, 658, 446, 486, 479, 398, 1041, 587, - 622, 443, 460, 610, 609, 597, 459, 640, 403, 920, - 467, 444, 934, 336, 942, 701, 1073, 617, 469, 950, - 618, 957, 960, 510, 511, 458, 972, 273, 470, 1000, - 641, 985, 620, 998, 453, 1004, 436, 1012, 1226, 437, - 1016, 260, 1019, 274, 404, 419, 1024, 1025, 8, 1031, - 664, 665, 10, 270, 490, 1056, 659, 433, 1072, 423, - 1142, 1144, 538, 471, 1162, 1161, 652, 487, 1167, 1229, - 431, 512, 454, 304, 513, 296, 322, 301, 528, 283, - 323, 514, 455, 1235, 1243, 319, 29, 1263, 1274, 330, - 556, 592 + -32768, 499, 711, 4, 712, 905, 788, 797, 583, 515, + 679, 339, 610, 413, 1255, 882, 1078, 565, 816, 1199, + 1207, 446, 819, 324, 701, 864, 865, 866, 391, 376, + 382, 389, 632, 611, 481, 851, 442, 843, 473, 846, + 441, 855, 162, 410, 497, 859, 3, 861, 542, 892, + 377, 869, 378, 656, 871, 550, 873, 874, 385, 392, + 393, 1083, 558, 607, 886, 243, 552, 887, 375, 888, + 895, 380, 383, 665, 453, 492, 486, 403, 1058, 594, + 629, 450, 467, 617, 616, 604, 466, 425, 408, 928, + 474, 451, 942, 341, 950, 709, 1090, 624, 476, 958, + 625, 965, 968, 516, 517, 465, 980, 269, 983, 477, + 1015, 647, 648, 995, 626, 627, 1013, 460, 584, 1021, + 443, 1029, 1243, 444, 1033, 262, 1036, 276, 409, 426, + 1041, 1042, 8, 1048, 671, 672, 10, 273, 496, 1073, + 666, 440, 1089, 430, 1159, 1161, 544, 478, 1179, 1178, + 659, 493, 1184, 1246, 438, 518, 461, 310, 519, 302, + 327, 307, 534, 289, 328, 520, 462, 1252, 1260, 325, + 30, 1280, 1291, 335, 562, 599 ); protected $ruleToNonTerminal = array( @@ -868,16 +865,17 @@ class Php7 extends \PhpParser\ParserAbstract 93, 94, 94, 95, 95, 96, 97, 97, 98, 98, 99, 99, 54, 54, 50, 50, 101, 52, 52, 102, 51, 51, 53, 53, 63, 63, 63, 63, 79, 79, - 105, 105, 107, 107, 107, 107, 107, 106, 106, 106, - 109, 109, 109, 87, 87, 111, 111, 111, 110, 110, - 112, 112, 113, 113, 113, 108, 108, 80, 80, 80, - 20, 20, 114, 114, 115, 115, 115, 115, 59, 116, - 116, 117, 60, 119, 119, 120, 120, 121, 121, 84, - 122, 122, 122, 122, 122, 122, 127, 127, 128, 128, - 129, 129, 129, 129, 129, 130, 131, 131, 126, 126, - 123, 123, 125, 125, 133, 133, 132, 132, 132, 132, - 132, 132, 132, 124, 134, 134, 136, 135, 135, 61, - 100, 137, 137, 55, 55, 42, 42, 42, 42, 42, + 105, 105, 107, 107, 108, 108, 108, 108, 106, 106, + 106, 110, 110, 110, 110, 87, 87, 113, 113, 113, + 111, 111, 114, 114, 112, 112, 115, 115, 116, 116, + 116, 116, 109, 109, 80, 80, 80, 20, 20, 20, + 118, 117, 117, 119, 119, 119, 119, 59, 120, 120, + 121, 60, 123, 123, 124, 124, 125, 125, 84, 126, + 126, 126, 126, 126, 126, 131, 131, 132, 132, 133, + 133, 133, 133, 133, 134, 135, 135, 130, 130, 127, + 127, 129, 129, 137, 137, 136, 136, 136, 136, 136, + 136, 136, 128, 138, 138, 140, 139, 139, 61, 100, + 141, 141, 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, @@ -886,20 +884,20 @@ class Php7 extends \PhpParser\ParserAbstract 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, 144, 138, - 138, 143, 143, 146, 147, 147, 148, 149, 149, 149, - 19, 19, 72, 72, 72, 72, 139, 139, 139, 139, - 151, 151, 140, 140, 142, 142, 142, 145, 145, 156, - 156, 156, 156, 156, 156, 156, 156, 156, 157, 157, - 104, 159, 159, 159, 159, 141, 141, 141, 141, 141, - 141, 141, 141, 58, 58, 154, 154, 154, 154, 160, - 160, 150, 150, 150, 161, 161, 161, 161, 161, 161, - 73, 73, 65, 65, 65, 65, 118, 118, 118, 118, - 164, 163, 153, 153, 153, 153, 153, 153, 153, 152, - 152, 152, 162, 162, 162, 162, 103, 158, 166, 166, - 165, 165, 167, 167, 167, 167, 167, 167, 167, 167, - 155, 155, 155, 155, 169, 170, 168, 168, 168, 168, - 168, 168, 168, 168, 171, 171, 171, 171 + 42, 42, 42, 42, 42, 42, 42, 148, 142, 142, + 147, 147, 150, 151, 151, 152, 153, 153, 153, 19, + 19, 72, 72, 72, 72, 143, 143, 143, 143, 155, + 155, 144, 144, 146, 146, 146, 149, 149, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 161, 161, 104, + 163, 163, 163, 163, 145, 145, 145, 145, 145, 145, + 145, 145, 58, 58, 158, 158, 158, 158, 164, 164, + 154, 154, 154, 165, 165, 165, 165, 165, 165, 73, + 73, 65, 65, 65, 65, 122, 122, 122, 122, 168, + 167, 157, 157, 157, 157, 157, 157, 157, 156, 156, + 156, 166, 166, 166, 166, 103, 162, 170, 170, 169, + 169, 171, 171, 171, 171, 171, 171, 171, 171, 159, + 159, 159, 159, 173, 174, 172, 172, 172, 172, 172, + 172, 172, 172, 175, 175, 175, 175 ); protected $ruleToLength = array( @@ -930,38 +928,39 @@ class Php7 extends \PhpParser\ParserAbstract 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, 1, 1, 1, 1, 6, 8, 6, - 1, 2, 1, 1, 1, 1, 1, 1, 3, 3, - 3, 3, 1, 2, 1, 0, 1, 0, 2, 2, - 2, 4, 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, + 1, 3, 0, 2, 1, 1, 1, 1, 6, 8, + 6, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 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, 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, 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 + 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, 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() { @@ -1814,57 +1813,57 @@ class Php7 extends \PhpParser\ParserAbstract $this->semValue = 0; }, 273 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + $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)]; }, 274 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; }, 275 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; }, 276 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_READONLY; + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; }, 277 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_READONLY; + }, + 278 => 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); }, - 278 => function ($stackPos) { + 279 => 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); }, - 279 => function ($stackPos) { + 280 => 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)]); }, - 280 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, 281 => function ($stackPos) { - $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 282 => function ($stackPos) { - $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 283 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 284 => function ($stackPos) { - $this->semValue = new Node\Name('static', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 285 => function ($stackPos) { - $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos-(1-1)]); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 286 => function ($stackPos) { - $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = new Node\Name('static', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 287 => function ($stackPos) { - $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos-(1-1)]); }, 288 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 289 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 290 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); @@ -1873,692 +1872,692 @@ class Php7 extends \PhpParser\ParserAbstract $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 292 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, 293 => function ($stackPos) { - $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 294 => function ($stackPos) { - $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, 295 => function ($stackPos) { - $this->semValue = null; + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 296 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, 297 => function ($stackPos) { - $this->semValue = null; + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 298 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 299 => function ($stackPos) { - $this->semValue = null; - }, - 300 => function ($stackPos) { - $this->semValue = array(); - }, - 301 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 302 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 303 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 304 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 305 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 306 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 307 => 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)]); - }, - 308 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 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 = array($this->semStack[$stackPos-(1-1)]); - }, - 311 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 312 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; + 299 => function ($stackPos) { + $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 313 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + 300 => function ($stackPos) { + $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 314 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); + 301 => function ($stackPos) { + $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 315 => function ($stackPos) { - $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + 302 => function ($stackPos) { + $this->semValue = null; }, - 316 => function ($stackPos) { - $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + 303 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 317 => 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)]; } + 304 => function ($stackPos) { + $this->semValue = null; }, - 318 => function ($stackPos) { + 305 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 306 => function ($stackPos) { + $this->semValue = null; + }, + 307 => function ($stackPos) { $this->semValue = array(); }, + 308 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 309 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-2)]); + }, + 310 => function ($stackPos) { + $this->semValue = new Node\VariadicPlaceholder($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 311 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 312 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 313 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 314 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 315 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 316 => 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)]); + }, + 317 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 318 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, 319 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 320 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 321 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 322 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 323 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 324 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 325 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 326 => 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)]; } + }, + 327 => function ($stackPos) { + $this->semValue = array(); + }, + 328 => 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)]; }, - 320 => function ($stackPos) { + 329 => 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)); }, - 321 => function ($stackPos) { + 330 => 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)); }, - 322 => function ($stackPos) { + 331 => 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)); }, - 323 => function ($stackPos) { + 332 => function ($stackPos) { $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 324 => function ($stackPos) { + 333 => 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); }, - 325 => function ($stackPos) { + 334 => function ($stackPos) { $this->semValue = null; /* will be skipped */ }, - 326 => function ($stackPos) { - $this->semValue = array(); - }, - 327 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 328 => function ($stackPos) { - $this->semValue = array(); - }, - 329 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 330 => 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); - }, - 331 => 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); - }, - 332 => 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); - }, - 333 => 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); - }, - 334 => 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); - }, 335 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + $this->semValue = array(); }, 336 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 337 => function ($stackPos) { - $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); - }, - 338 => function ($stackPos) { - $this->semValue = null; - }, - 339 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 340 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 341 => function ($stackPos) { - $this->semValue = 0; - }, - 342 => function ($stackPos) { - $this->semValue = 0; - }, - 343 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 344 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 345 => 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)]; - }, - 346 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; - }, - 347 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; - }, - 348 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; - }, - 349 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_STATIC; - }, - 350 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; - }, - 351 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_FINAL; - }, - 352 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_READONLY; - }, - 353 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 354 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 355 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 356 => function ($stackPos) { - $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 357 => function ($stackPos) { - $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 358 => function ($stackPos) { - $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 359 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 360 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 361 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 362 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 363 => function ($stackPos) { - $this->semValue = array(); - }, - 364 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 365 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 366 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 367 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 368 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 369 => function ($stackPos) { - $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 370 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 371 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 372 => function ($stackPos) { - $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 373 => 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); - }, - 374 => 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); - }, - 375 => 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); - }, - 376 => 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); - }, - 377 => 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); - }, - 378 => 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); - }, - 379 => 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); - }, - 380 => 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); - }, - 381 => 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); - }, - 382 => 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); - }, - 383 => 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); - }, - 384 => 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); - }, - 385 => 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); - }, - 386 => function ($stackPos) { - $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 387 => function ($stackPos) { - $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 388 => function ($stackPos) { - $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 389 => function ($stackPos) { - $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 390 => 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); - }, - 391 => 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); - }, - 392 => 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); - }, - 393 => 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); - }, - 394 => 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); - }, - 395 => 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); - }, - 396 => 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); - }, - 397 => 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); - }, - 398 => 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); - }, - 399 => 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); - }, - 400 => 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); - }, - 401 => 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); - }, - 402 => 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); - }, - 403 => 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); - }, - 404 => 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); - }, - 405 => 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); - }, - 406 => 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); - }, - 407 => 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); - }, - 408 => function ($stackPos) { - $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 409 => function ($stackPos) { - $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 410 => function ($stackPos) { - $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 411 => function ($stackPos) { - $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 412 => 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); - }, - 413 => 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); - }, - 414 => 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); - }, - 415 => 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); - }, - 416 => 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); - }, - 417 => 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); - }, - 418 => 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); - }, - 419 => 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); - }, - 420 => 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); - }, - 421 => function ($stackPos) { - $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 422 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, + 337 => function ($stackPos) { + $this->semValue = array(); + }, + 338 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 339 => 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); + }, + 340 => 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); + }, + 341 => 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); + }, + 342 => 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); + }, + 343 => 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); + }, + 344 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 345 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 346 => function ($stackPos) { + $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); + }, + 347 => function ($stackPos) { + $this->semValue = null; + }, + 348 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 349 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 350 => function ($stackPos) { + $this->semValue = 0; + }, + 351 => function ($stackPos) { + $this->semValue = 0; + }, + 352 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 353 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 354 => 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)]; + }, + 355 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + }, + 356 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + }, + 357 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + }, + 358 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_STATIC; + }, + 359 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + }, + 360 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + }, + 361 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_READONLY; + }, + 362 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 363 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 364 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 365 => function ($stackPos) { + $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 366 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 367 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 368 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 369 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 370 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 371 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 372 => function ($stackPos) { + $this->semValue = array(); + }, + 373 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 374 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 375 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 376 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 377 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 378 => function ($stackPos) { + $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 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\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 382 => 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); + }, + 383 => 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); + }, + 384 => 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); + }, + 385 => 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); + }, + 386 => 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); + }, + 387 => 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); + }, + 388 => 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); + }, + 389 => 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); + }, + 390 => 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); + }, + 391 => 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); + }, + 392 => 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); + }, + 393 => 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); + }, + 394 => 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); + }, + 395 => function ($stackPos) { + $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 396 => function ($stackPos) { + $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 397 => function ($stackPos) { + $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 398 => function ($stackPos) { + $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 399 => 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); + }, + 400 => 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); + }, + 401 => 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); + }, + 402 => 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); + }, + 403 => 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); + }, + 404 => 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); + }, + 405 => 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); + }, + 406 => 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); + }, + 407 => 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); + }, + 408 => 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); + }, + 409 => 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); + }, + 410 => 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); + }, + 411 => 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); + }, + 412 => 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); + }, + 413 => 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); + }, + 414 => 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); + }, + 415 => 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); + }, + 416 => 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); + }, + 417 => function ($stackPos) { + $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 418 => function ($stackPos) { + $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 419 => function ($stackPos) { + $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 420 => function ($stackPos) { + $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 421 => 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); + }, + 422 => 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); + }, 423 => 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); + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 424 => 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); + $this->semValue = new Expr\BinaryOp\NotEqual($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\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 426 => function ($stackPos) { - $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 427 => function ($stackPos) { - $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 428 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 429 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 430 => function ($stackPos) { - $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 431 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 432 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $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); }, 433 => function ($stackPos) { - $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 434 => 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); + }, + 435 => function ($stackPos) { + $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 436 => function ($stackPos) { + $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 437 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 438 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 439 => function ($stackPos) { + $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 440 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 441 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 442 => function ($stackPos) { + $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 443 => 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); }, - 435 => function ($stackPos) { + 444 => function ($stackPos) { $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 436 => function ($stackPos) { + 445 => function ($stackPos) { $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 437 => function ($stackPos) { + 446 => function ($stackPos) { $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 438 => function ($stackPos) { + 447 => function ($stackPos) { $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 439 => function ($stackPos) { + 448 => function ($stackPos) { $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 440 => function ($stackPos) { + 449 => 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); }, - 441 => function ($stackPos) { + 450 => function ($stackPos) { $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 442 => function ($stackPos) { + 451 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 443 => function ($stackPos) { + 452 => function ($stackPos) { $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 444 => function ($stackPos) { + 453 => function ($stackPos) { $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 445 => function ($stackPos) { + 454 => function ($stackPos) { $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 446 => function ($stackPos) { + 455 => function ($stackPos) { $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 447 => function ($stackPos) { + 456 => function ($stackPos) { $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 448 => function ($stackPos) { + 457 => function ($stackPos) { $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 449 => function ($stackPos) { + 458 => function ($stackPos) { $this->semValue = new Expr\Throw_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 450 => function ($stackPos) { + 459 => 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); }, - 451 => function ($stackPos) { + 460 => 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); }, - 452 => function ($stackPos) { + 461 => 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); }, - 453 => function ($stackPos) { + 462 => 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); }, - 454 => function ($stackPos) { + 463 => 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); }, - 455 => function ($stackPos) { + 464 => 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); }, - 456 => function ($stackPos) { + 465 => 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); }, - 457 => function ($stackPos) { + 466 => 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); }, - 458 => function ($stackPos) { + 467 => 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); }, - 459 => function ($stackPos) { + 468 => function ($stackPos) { $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 460 => function ($stackPos) { + 469 => function ($stackPos) { list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 461 => function ($stackPos) { + 470 => function ($stackPos) { $this->semValue = array(); }, - 462 => function ($stackPos) { + 471 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-3)]; }, - 463 => function ($stackPos) { + 472 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 464 => function ($stackPos) { + 473 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 465 => function ($stackPos) { + 474 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, - 466 => function ($stackPos) { + 475 => function ($stackPos) { $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 467 => function ($stackPos) { - $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 468 => function ($stackPos) { - $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 469 => 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); - }, - 470 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 471 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 472 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 473 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 474 => function ($stackPos) { - $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 475 => function ($stackPos) { - $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, 476 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 477 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 478 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; + $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); }, 479 => function ($stackPos) { - $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 480 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 481 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 482 => function ($stackPos) { - $this->semValue = null; + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 483 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; + $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 484 => function ($stackPos) { - $this->semValue = array(); + $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 485 => function ($stackPos) { - $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`'), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); - }, - 486 => 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)]; - }, - 487 => function ($stackPos) { - $this->semValue = array(); - }, - 488 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, + 486 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 487 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 488 => function ($stackPos) { + $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + }, 489 => function ($stackPos) { - $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 490 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 491 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = null; }, 492 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 493 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = array(); }, 494 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`'), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); }, 495 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + 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)]; }, 496 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = array(); }, 497 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 498 => function ($stackPos) { - $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 499 => 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; + $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 500 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 501 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 502 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 503 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 504 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 505 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 506 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 507 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 508 => 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; + }, + 509 => 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); }, - 501 => function ($stackPos) { + 510 => 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); }, - 502 => function ($stackPos) { + 511 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 503 => function ($stackPos) { + 512 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(1-1)][0] === "'" || ($this->semStack[$stackPos-(1-1)][1] === "'" && ($this->semStack[$stackPos-(1-1)][0] === 'b' || $this->semStack[$stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED); $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos-(1-1)]), $attrs); }, - 504 => function ($stackPos) { + 513 => 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); }, - 505 => function ($stackPos) { + 514 => function ($stackPos) { $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 506 => function ($stackPos) { + 515 => function ($stackPos) { $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 507 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 508 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 509 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 510 => 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); - }, - 511 => 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); - }, - 512 => 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); - }, - 513 => function ($stackPos) { - $this->semValue = null; - }, - 514 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 515 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, 516 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 517 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; @@ -2567,16 +2566,16 @@ class Php7 extends \PhpParser\ParserAbstract $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 519 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $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); }, 520 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $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); }, 521 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $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); }, 522 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; + $this->semValue = null; }, 523 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; @@ -2585,25 +2584,25 @@ class Php7 extends \PhpParser\ParserAbstract $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 525 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 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); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 527 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 528 => 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); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 529 => 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); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 530 => function ($stackPos) { - $this->semValue = null; + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 531 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; + $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 532 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; @@ -2612,165 +2611,192 @@ class Php7 extends \PhpParser\ParserAbstract $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 534 => function ($stackPos) { - $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 535 => function ($stackPos) { - $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 536 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 537 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $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); }, 538 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $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); }, 539 => 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; + $this->semValue = null; }, 540 => 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; + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 541 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 542 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 543 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 544 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 545 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 546 => function ($stackPos) { + 544 => function ($stackPos) { $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 547 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 548 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 549 => function ($stackPos) { + 545 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, + 546 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 547 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 548 => 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; + }, + 549 => 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; + }, 550 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 551 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 552 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 553 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 554 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 555 => function ($stackPos) { - $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; - }, - 556 => function ($stackPos) { - $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 557 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) array_pop($this->semValue); - }, - 558 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 559 => function ($stackPos) { - /* do nothing -- prevent default action of $$=$this->semStack[$1]. See $551. */ - }, - 560 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 561 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 562 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 563 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 564 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 565 => 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); - }, - 566 => 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); - }, - 567 => 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); - }, - 568 => 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); - }, - 569 => function ($stackPos) { - $this->semValue = null; - }, - 570 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 571 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 572 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 573 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); - }, - 574 => function ($stackPos) { - $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 575 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 576 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 577 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 578 => function ($stackPos) { + 553 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 554 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 579 => function ($stackPos) { + 555 => function ($stackPos) { $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 580 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + 556 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 581 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + 557 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 582 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + 558 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 583 => function ($stackPos) { + 559 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, + 560 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 561 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 562 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 563 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 564 => function ($stackPos) { + $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + }, + 565 => function ($stackPos) { + $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 566 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) array_pop($this->semValue); + }, + 567 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 568 => function ($stackPos) { + /* do nothing -- prevent default action of $$=$this->semStack[$1]. See $551. */ + }, + 569 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 570 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 571 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 572 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 573 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 574 => 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); + }, + 575 => 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); + }, + 576 => 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); + }, + 577 => 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); + }, + 578 => function ($stackPos) { + $this->semValue = null; + }, + 579 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 580 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 581 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 582 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); + }, + 583 => function ($stackPos) { + $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, 584 => function ($stackPos) { - $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, 585 => function ($stackPos) { - $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 586 => function ($stackPos) { - $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, 587 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 588 => function ($stackPos) { + $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 589 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 590 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 591 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 592 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 593 => function ($stackPos) { + $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 594 => function ($stackPos) { + $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 595 => function ($stackPos) { + $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 596 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, ]; diff --git a/lib/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php b/lib/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php index 62d1f34c1..bb70de659 100644 --- a/lib/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php +++ b/lib/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php @@ -33,6 +33,10 @@ class Standard extends PrettyPrinterAbstract . $this->p($node->value); } + protected function pVariadicPlaceholder(Node\VariadicPlaceholder $node) { + return '...'; + } + protected function pConst(Node\Const_ $node) { return $node->name . ' = ' . $this->p($node->value); } @@ -45,6 +49,10 @@ class Standard extends PrettyPrinterAbstract return $this->pImplode($node->types, '|'); } + protected function pIntersectionType(Node\IntersectionType $node) { + return $this->pImplode($node->types, '&'); + } + protected function pIdentifier(Node\Identifier $node) { return $node->name; } diff --git a/lib/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php b/lib/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php index 8a3565f1c..2c7fc3070 100644 --- a/lib/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php +++ b/lib/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php @@ -824,7 +824,11 @@ abstract class PrettyPrinterAbstract return null; } - if ($insertStr === ', ' && $this->isMultiline($origNodes)) { + // 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; } @@ -842,11 +846,11 @@ abstract class PrettyPrinterAbstract $this->setIndentLevel($lastElemIndentLevel); if ($insertNewline) { + $result .= $insertStr . $this->nl; $comments = $arrItem->getComments(); if ($comments) { - $result .= $this->nl . $this->pComments($comments); + $result .= $this->pComments($comments) . $this->nl; } - $result .= $insertStr . $this->nl; } else { $result .= $insertStr; } @@ -1343,6 +1347,7 @@ abstract class PrettyPrinterAbstract //'Scalar_Encapsed->parts' => '', 'Stmt_Catch->types' => '|', 'UnionType->types' => '|', + 'IntersectionType->types' => '&', 'Stmt_If->elseifs' => ' ', 'Stmt_TryCatch->catches' => ' ', diff --git a/lib/scssphp/scssphp/README.md b/lib/scssphp/scssphp/README.md index f541e4888..65bb93ea7 100644 --- a/lib/scssphp/scssphp/README.md +++ b/lib/scssphp/scssphp/README.md @@ -1,12 +1,12 @@ # scssphp -### +### -[![Build](https://travis-ci.org/scssphp/scssphp.svg?branch=master)](http://travis-ci.org/scssphp/scssphp) +![Build](https://github.com/scssphp/scssphp/workflows/CI/badge.svg) [![License](https://poser.pugx.org/scssphp/scssphp/license)](https://packagist.org/packages/scssphp/scssphp) `scssphp` is a compiler for SCSS written in PHP. -Checkout the homepage, , for directions on how to use. +Checkout the homepage, , for directions on how to use. ## Running Tests @@ -23,8 +23,7 @@ There are several tests in the `tests/` directory: * `FailingTest.php` contains tests reported in Github issues that demonstrate compatibility bugs. * `InputTest.php` compiles every `.scss` file in the `tests/inputs` directory then compares to the respective `.css` file in the `tests/outputs` directory. -* `ScssTest.php` extracts (ruby) `scss` tests from the `tests/scss_test.rb` file. -* `ServerTest.php` contains functional tests for the `Server` class. +* `SassSpecTest.php` extracts tests from the `sass/sass-spec` repository. When changing any of the tests in `tests/inputs`, the tests will most likely fail because the output has changed. Once you verify that the output is correct @@ -32,16 +31,41 @@ you can run the following command to rebuild all the tests: BUILD=1 vendor/bin/phpunit tests -This will compile all the tests, and save results into `tests/outputs`. +This will compile all the tests, and save results into `tests/outputs`. It also +updates the list of excluded specs from sass-spec. -To enable the `scss` compatibility tests: +To enable the full `sass-spec` compatibility tests: - TEST_SCSS_COMPAT=1 vendor/bin/phpunit tests + TEST_SASS_SPEC=1 vendor/bin/phpunit tests ## Coding Standard -`scssphp` source conforms to [PSR2](http://www.php-fig.org/psr/psr-2/). +`scssphp` source conforms to [PSR12](https://www.php-fig.org/psr/psr-12/). Run the following command from the root directory to check the code for "sniffs". - vendor/bin/phpcs --standard=PSR2 bin src tests + vendor/bin/phpcs --standard=PSR12 --extensions=php bin src tests *.php + +## Static Analysis + +`scssphp` uses [phpstan](https://phpstan.org/) for static analysis. + +Run the following command from the root directory to analyse the codebase: + + make phpstan + +As most of the codebase is composed of legacy code which cannot be type-checked +fully, the setup contains a baseline file with all errors we want to ignore. In +particular, we ignore all errors related to not specifying the types inside arrays +when these arrays correspond to the representation of Sass values and Sass AST nodes +in the parser and compiler. +When contributing, the proper process to deal with static analysis is the following: + +1. Make your change in the codebase +2. Run `make phpstan` +3. Fix errors reported by phpstan when possible +4. Repeat step 2 and 3 until nothing gets fixed anymore at step 3 +5. Run `make phpstan-baseline` to regenerate the phpstan baseline + +Additions to the baseline will be reviewed to avoid ignoring errors that should have +been fixed. diff --git a/lib/scssphp/scssphp/bin/pscss b/lib/scssphp/scssphp/bin/pscss index f944b6325..0f009d6bd 100644 --- a/lib/scssphp/scssphp/bin/pscss +++ b/lib/scssphp/scssphp/bin/pscss @@ -1,9 +1,10 @@ #!/usr/bin/env php parse($data)), true)); + fwrite(STDERR, 'Warning: the --dump-tree option is deprecated. Use proper debugging tools instead.'); + exit(); } $scss = new Compiler(); -if ($debugInfo) { - $scss->setLineNumberStyle(Compiler::DEBUG_INFO); -} - -if ($lineNumbers) { - $scss->setLineNumberStyle(Compiler::LINE_COMMENTS); -} - -if ($ignoreErrors) { - $scss->setIgnoreErrors($ignoreErrors); -} - if ($loadPaths) { - $scss->setImportPaths(explode(PATH_SEPARATOR, $loadPaths)); -} - -if ($precision) { - $scss->setNumberPrecision($precision); + $scss->setImportPaths($loadPaths); } if ($style) { - $scss->setFormatter('ScssPhp\\ScssPhp\\Formatter\\' . ucfirst($style)); + if ($style === OutputStyle::COMPRESSED || $style === OutputStyle::EXPANDED) { + $scss->setOutputStyle($style); + } else { + fwrite(STDERR, "WARNING: the $style style is deprecated.\n"); + $scss->setFormatter('ScssPhp\\ScssPhp\\Formatter\\' . ucfirst($style)); + } } +$outputFile = isset($arguments[1]) ? $arguments[1] : null; +$sourceMapFile = null; + if ($sourceMap) { - $scss->setSourceMap(Compiler::SOURCE_MAP_INLINE); + $sourceMapOptions = array( + 'outputSourceFiles' => $embedSources, + ); + if ($embedSourceMap || $outputFile === null) { + $scss->setSourceMap(Compiler::SOURCE_MAP_INLINE); + } else { + $sourceMapFile = $outputFile . '.map'; + $sourceMapOptions['sourceMapWriteTo'] = $sourceMapFile; + $sourceMapOptions['sourceMapURL'] = basename($sourceMapFile); + $sourceMapOptions['sourceMapBasepath'] = getcwd(); + $sourceMapOptions['sourceMapFilename'] = basename($outputFile); + + $scss->setSourceMap(Compiler::SOURCE_MAP_FILE); + } + + $scss->setSourceMapOptions($sourceMapOptions); } if ($encoding) { $scss->setEncoding($encoding); } -echo $scss->compile($data, $inputFile); - -if ($changeDir) { - chdir($oldWorkingDir); +try { + $result = $scss->compileString($data, $inputFile); +} catch (SassException $e) { + fwrite(STDERR, 'Error: '.$e->getMessage()."\n"); + exit(1); +} + +if ($outputFile) { + file_put_contents($outputFile, $result->getCss()); + + if ($sourceMapFile !== null && $result->getSourceMap() !== null) { + file_put_contents($sourceMapFile, $result->getSourceMap()); + } +} else { + echo $result->getCss(); } diff --git a/lib/scssphp/scssphp/composer.json b/lib/scssphp/scssphp/composer.json index ff0590fbd..3c60ca897 100644 --- a/lib/scssphp/scssphp/composer.json +++ b/lib/scssphp/scssphp/composer.json @@ -30,22 +30,82 @@ "ext-json": "*", "ext-ctype": "*" }, + "suggest": { + "ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv", + "ext-iconv": "Can be used as fallback when ext-mbstring is not available" + }, "require-dev": { - "squizlabs/php_codesniffer": "~2.5", - "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3", - "twbs/bootstrap": "~4.3", + "bamarni/composer-bin-plugin": "^1.4", + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4", + "sass/sass-spec": "*", + "squizlabs/php_codesniffer": "~3.5", + "symfony/phpunit-bridge": "^5.1", + "thoughtbot/bourbon": "^7.0", + "twbs/bootstrap": "~5.0", + "twbs/bootstrap4": "4.6.1", "zurb/foundation": "~6.5" }, - "minimum-stability": "dev", + "repositories": [ + { + "type": "package", + "package": { + "name": "sass/sass-spec", + "version": "2022.02.24", + "source": { + "type": "git", + "url": "https://github.com/sass/sass-spec.git", + "reference": "f41b9bfb9a3013392f2136c79f7f3356f15fb8ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sass/sass-spec/zipball/f41b9bfb9a3013392f2136c79f7f3356f15fb8ba", + "reference": "f41b9bfb9a3013392f2136c79f7f3356f15fb8ba", + "shasum": "" + } + } + }, + { + "type": "package", + "package": { + "name": "thoughtbot/bourbon", + "version": "v7.0.0", + "source": { + "type": "git", + "url": "https://github.com/thoughtbot/bourbon.git", + "reference": "fbe338ee6807e7f7aa996d82c8a16f248bb149b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thoughtbot/bourbon/zipball/fbe338ee6807e7f7aa996d82c8a16f248bb149b3", + "reference": "fbe338ee6807e7f7aa996d82c8a16f248bb149b3", + "shasum": "" + } + } + }, + { + "type": "package", + "package": { + "name": "twbs/bootstrap4", + "version": "v4.6.1", + "source": { + "type": "git", + "url": "https://github.com/twbs/bootstrap.git", + "reference": "043a03c95a2ad6738f85b65e53b9dbdfb03b8d10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twbs/bootstrap/zipball/043a03c95a2ad6738f85b65e53b9dbdfb03b8d10", + "reference": "043a03c95a2ad6738f85b65e53b9dbdfb03b8d10", + "shasum": "" + } + } + } + ], "bin": ["bin/pscss"], - "archive": { - "exclude": [ - "/Makefile", - "/.gitattributes", - "/.gitignore", - "/.travis.yml", - "/phpunit.xml.dist", - "/tests" - ] + "config": { + "sort-packages": true, + "allow-plugins": { + "bamarni/composer-bin-plugin": true + } } } diff --git a/lib/scssphp/scssphp/phpcs.xml.dist b/lib/scssphp/scssphp/phpcs.xml.dist new file mode 100644 index 000000000..b162dbd6b --- /dev/null +++ b/lib/scssphp/scssphp/phpcs.xml.dist @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/lib/scssphp/scssphp/scss.inc.php b/lib/scssphp/scssphp/scss.inc.php index e4ec7f181..459837805 100644 --- a/lib/scssphp/scssphp/scss.inc.php +++ b/lib/scssphp/scssphp/scss.inc.php @@ -1,34 +1,21 @@ + * + * @internal */ class Range { + /** + * @var float|int + */ public $first; + + /** + * @var float|int + */ public $last; /** * Initialize range * - * @param integer|float $first - * @param integer|float $last + * @param int|float $first + * @param int|float $last */ public function __construct($first, $last) { @@ -36,9 +46,9 @@ class Range /** * Test for inclusion in range * - * @param integer|float $value + * @param int|float $value * - * @return boolean + * @return bool */ public function includes($value) { diff --git a/lib/scssphp/scssphp/src/Block.php b/lib/scssphp/scssphp/src/Block.php index bb1afdd4b..96668dc66 100644 --- a/lib/scssphp/scssphp/src/Block.php +++ b/lib/scssphp/scssphp/src/Block.php @@ -1,8 +1,9 @@ + * + * @internal */ class Block { /** - * @var string + * @var string|null */ public $type; /** - * @var \ScssPhp\ScssPhp\Block + * @var Block|null */ public $parent; @@ -34,22 +37,22 @@ class Block public $sourceName; /** - * @var integer + * @var int */ public $sourceIndex; /** - * @var integer + * @var int */ public $sourceLine; /** - * @var integer + * @var int */ public $sourceColumn; /** - * @var array + * @var array|null */ public $selectors; @@ -64,7 +67,7 @@ class Block public $children; /** - * @var \ScssPhp\ScssPhp\Block + * @var Block|null */ public $selfParent; } diff --git a/lib/scssphp/scssphp/src/Block/AtRootBlock.php b/lib/scssphp/scssphp/src/Block/AtRootBlock.php new file mode 100644 index 000000000..41842c269 --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/AtRootBlock.php @@ -0,0 +1,37 @@ +type = Type::T_AT_ROOT; + } +} diff --git a/lib/scssphp/scssphp/src/Block/CallableBlock.php b/lib/scssphp/scssphp/src/Block/CallableBlock.php new file mode 100644 index 000000000..a18a87c2a --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/CallableBlock.php @@ -0,0 +1,45 @@ +type = $type; + } +} diff --git a/lib/scssphp/scssphp/src/Block/ContentBlock.php b/lib/scssphp/scssphp/src/Block/ContentBlock.php new file mode 100644 index 000000000..870849800 --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/ContentBlock.php @@ -0,0 +1,38 @@ +type = Type::T_INCLUDE; + } +} diff --git a/lib/scssphp/scssphp/src/Block/DirectiveBlock.php b/lib/scssphp/scssphp/src/Block/DirectiveBlock.php new file mode 100644 index 000000000..b1d3d1a81 --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/DirectiveBlock.php @@ -0,0 +1,37 @@ +type = Type::T_DIRECTIVE; + } +} diff --git a/lib/scssphp/scssphp/src/Block/EachBlock.php b/lib/scssphp/scssphp/src/Block/EachBlock.php new file mode 100644 index 000000000..b3289579d --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/EachBlock.php @@ -0,0 +1,37 @@ +type = Type::T_EACH; + } +} diff --git a/lib/scssphp/scssphp/src/Block/ElseBlock.php b/lib/scssphp/scssphp/src/Block/ElseBlock.php new file mode 100644 index 000000000..6abb4d775 --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/ElseBlock.php @@ -0,0 +1,27 @@ +type = Type::T_ELSE; + } +} diff --git a/lib/scssphp/scssphp/src/Block/ElseifBlock.php b/lib/scssphp/scssphp/src/Block/ElseifBlock.php new file mode 100644 index 000000000..4622bca79 --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/ElseifBlock.php @@ -0,0 +1,32 @@ +type = Type::T_ELSEIF; + } +} diff --git a/lib/scssphp/scssphp/src/Block/ForBlock.php b/lib/scssphp/scssphp/src/Block/ForBlock.php new file mode 100644 index 000000000..a9cf6733b --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/ForBlock.php @@ -0,0 +1,47 @@ +type = Type::T_FOR; + } +} diff --git a/lib/scssphp/scssphp/src/Block/IfBlock.php b/lib/scssphp/scssphp/src/Block/IfBlock.php new file mode 100644 index 000000000..9f21bf88a --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/IfBlock.php @@ -0,0 +1,37 @@ + + */ + public $cases = []; + + public function __construct() + { + $this->type = Type::T_IF; + } +} diff --git a/lib/scssphp/scssphp/src/Block/MediaBlock.php b/lib/scssphp/scssphp/src/Block/MediaBlock.php new file mode 100644 index 000000000..c49ee1b2b --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/MediaBlock.php @@ -0,0 +1,37 @@ +type = Type::T_MEDIA; + } +} diff --git a/lib/scssphp/scssphp/src/Block/NestedPropertyBlock.php b/lib/scssphp/scssphp/src/Block/NestedPropertyBlock.php new file mode 100644 index 000000000..1ea4a6c8a --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/NestedPropertyBlock.php @@ -0,0 +1,37 @@ +type = Type::T_NESTED_PROPERTY; + } +} diff --git a/lib/scssphp/scssphp/src/Block/WhileBlock.php b/lib/scssphp/scssphp/src/Block/WhileBlock.php new file mode 100644 index 000000000..ac18d4e02 --- /dev/null +++ b/lib/scssphp/scssphp/src/Block/WhileBlock.php @@ -0,0 +1,32 @@ +type = Type::T_WHILE; + } +} diff --git a/lib/scssphp/scssphp/src/Cache.php b/lib/scssphp/scssphp/src/Cache.php index 422497f49..9731c60a7 100644 --- a/lib/scssphp/scssphp/src/Cache.php +++ b/lib/scssphp/scssphp/src/Cache.php @@ -1,8 +1,9 @@ + * + * @internal */ class Cache { const CACHE_VERSION = 1; - // directory used for storing data + /** + * directory used for storing data + * + * @var string|false + */ public static $cacheDir = false; - // prefix for the storing data + /** + * prefix for the storing data + * + * @var string + */ public static $prefix = 'scssphp_'; - // force a refresh : 'once' for refreshing the first hit on a cache only, true to never use the cache in this hit + /** + * force a refresh : 'once' for refreshing the first hit on a cache only, true to never use the cache in this hit + * + * @var bool|string + */ public static $forceRefresh = false; - // specifies the number of seconds after which data cached will be seen as 'garbage' and potentially cleaned up + /** + * specifies the number of seconds after which data cached will be seen as 'garbage' and potentially cleaned up + * + * @var int + */ public static $gcLifetime = 604800; - // array of already refreshed cache if $forceRefresh==='once' + /** + * array of already refreshed cache if $forceRefresh==='once' + * + * @var array + */ protected static $refreshed = []; /** * Constructor * * @param array $options + * + * @phpstan-param array{cacheDir?: string, prefix?: string, forceRefresh?: string} $options */ public function __construct($options) { @@ -84,10 +109,10 @@ class Cache * Get the cached result of $operation on $what, * which is known as dependant from the content of $options * - * @param string $operation parse, compile... - * @param mixed $what content key (e.g., filename to be treated) - * @param array $options any option that affect the operation result on the content - * @param integer $lastModified last modified timestamp + * @param string $operation parse, compile... + * @param mixed $what content key (e.g., filename to be treated) + * @param array $options any option that affect the operation result on the content + * @param int|null $lastModified last modified timestamp * * @return mixed * @@ -97,18 +122,20 @@ class Cache { $fileCache = self::$cacheDir . self::cacheName($operation, $what, $options); - if (((self::$forceRefresh === false) || (self::$forceRefresh === 'once' && + if ( + ((self::$forceRefresh === false) || (self::$forceRefresh === 'once' && isset(self::$refreshed[$fileCache]))) && file_exists($fileCache) ) { $cacheTime = filemtime($fileCache); - if ((is_null($lastModified) || $cacheTime > $lastModified) && + if ( + (\is_null($lastModified) || $cacheTime > $lastModified) && $cacheTime + self::$gcLifetime > time() ) { $c = file_get_contents($fileCache); $c = unserialize($c); - if (is_array($c) && isset($c['value'])) { + if (\is_array($c) && isset($c['value'])) { return $c['value']; } } @@ -125,6 +152,8 @@ class Cache * @param mixed $what * @param mixed $value * @param array $options + * + * @return void */ public function setCache($operation, $what, $value, $options = []) { @@ -132,6 +161,7 @@ class Cache $c = ['value' => $value]; $c = serialize($c); + file_put_contents($fileCache, $c); if (self::$forceRefresh === 'once') { @@ -153,6 +183,7 @@ class Cache { $t = [ 'version' => self::CACHE_VERSION, + 'scssphpVersion' => Version::VERSION, 'operation' => $operation, 'what' => $what, 'options' => $options @@ -169,6 +200,8 @@ class Cache /** * Check that the cache dir exists and is writeable * + * @return void + * * @throws \Exception */ public static function checkCacheDir() @@ -177,9 +210,7 @@ class Cache self::$cacheDir = rtrim(self::$cacheDir, '/') . '/'; if (! is_dir(self::$cacheDir)) { - if (! mkdir(self::$cacheDir)) { - throw new Exception('Cache directory couldn\'t be created: ' . self::$cacheDir); - } + throw new Exception('Cache directory doesn\'t exist: ' . self::$cacheDir); } if (! is_writable(self::$cacheDir)) { @@ -189,6 +220,8 @@ class Cache /** * Delete unused cached files + * + * @return void */ public static function cleanCache() { diff --git a/lib/scssphp/scssphp/src/Colors.php b/lib/scssphp/scssphp/src/Colors.php index ef6409aca..2df39992b 100644 --- a/lib/scssphp/scssphp/src/Colors.php +++ b/lib/scssphp/scssphp/src/Colors.php @@ -1,8 +1,9 @@ + * + * @internal */ class Colors { @@ -23,12 +26,13 @@ class Colors * * @see http://www.w3.org/TR/css3-color * - * @var array + * @var array */ protected static $cssColors = [ 'aliceblue' => '240,248,255', 'antiquewhite' => '250,235,215', 'aqua' => '0,255,255', + 'cyan' => '0,255,255', 'aquamarine' => '127,255,212', 'azure' => '240,255,255', 'beige' => '245,245,220', @@ -46,13 +50,12 @@ class Colors 'cornflowerblue' => '100,149,237', 'cornsilk' => '255,248,220', 'crimson' => '220,20,60', - 'cyan' => '0,255,255', 'darkblue' => '0,0,139', 'darkcyan' => '0,139,139', 'darkgoldenrod' => '184,134,11', 'darkgray' => '169,169,169', - 'darkgreen' => '0,100,0', 'darkgrey' => '169,169,169', + 'darkgreen' => '0,100,0', 'darkkhaki' => '189,183,107', 'darkmagenta' => '139,0,139', 'darkolivegreen' => '85,107,47', @@ -75,14 +78,15 @@ class Colors 'floralwhite' => '255,250,240', 'forestgreen' => '34,139,34', 'fuchsia' => '255,0,255', + 'magenta' => '255,0,255', 'gainsboro' => '220,220,220', 'ghostwhite' => '248,248,255', 'gold' => '255,215,0', 'goldenrod' => '218,165,32', 'gray' => '128,128,128', + 'grey' => '128,128,128', 'green' => '0,128,0', 'greenyellow' => '173,255,47', - 'grey' => '128,128,128', 'honeydew' => '240,255,240', 'hotpink' => '255,105,180', 'indianred' => '205,92,92', @@ -98,8 +102,8 @@ class Colors 'lightcyan' => '224,255,255', 'lightgoldenrodyellow' => '250,250,210', 'lightgray' => '211,211,211', - 'lightgreen' => '144,238,144', 'lightgrey' => '211,211,211', + 'lightgreen' => '144,238,144', 'lightpink' => '255,182,193', 'lightsalmon' => '255,160,122', 'lightseagreen' => '32,178,170', @@ -111,7 +115,6 @@ class Colors 'lime' => '0,255,0', 'limegreen' => '50,205,50', 'linen' => '250,240,230', - 'magenta' => '255,0,255', 'maroon' => '128,0,0', 'mediumaquamarine' => '102,205,170', 'mediumblue' => '0,0,205', @@ -145,7 +148,6 @@ class Colors 'plum' => '221,160,221', 'powderblue' => '176,224,230', 'purple' => '128,0,128', - 'rebeccapurple' => '102,51,153', 'red' => '255,0,0', 'rosybrown' => '188,143,143', 'royalblue' => '65,105,225', @@ -167,7 +169,6 @@ class Colors 'teal' => '0,128,128', 'thistle' => '216,191,216', 'tomato' => '255,99,71', - 'transparent' => '0,0,0,0', 'turquoise' => '64,224,208', 'violet' => '238,130,238', 'wheat' => '245,222,179', @@ -175,6 +176,8 @@ class Colors 'whitesmoke' => '245,245,245', 'yellow' => '255,255,0', 'yellowgreen' => '154,205,50', + 'rebeccapurple' => '102,51,153', + 'transparent' => '0,0,0,0', ]; /** @@ -182,11 +185,11 @@ class Colors * * @param string $colorName * - * @return array|null + * @return int[]|null */ public static function colorNameToRGBa($colorName) { - if (is_string($colorName) && isset(static::$cssColors[$colorName])) { + if (\is_string($colorName) && isset(static::$cssColors[$colorName])) { $rgba = explode(',', static::$cssColors[$colorName]); // only case with opacity is transparent, with opacity=0, so we can intval on opacity also @@ -201,10 +204,10 @@ class Colors /** * Reverse conversion : from RGBA to a color name if possible * - * @param integer $r - * @param integer $g - * @param integer $b - * @param integer $a + * @param int $r + * @param int $g + * @param int $b + * @param int|float $a * * @return string|null */ @@ -217,28 +220,26 @@ class Colors } if ($a < 1) { - # specific case we dont' revert according to spec - #if (! $a && ! $r && ! $g && ! $b) { - # return 'transparent'; - #} - return null; } - if (is_null($reverseColorTable)) { + if (\is_null($reverseColorTable)) { $reverseColorTable = []; foreach (static::$cssColors as $name => $rgb_str) { $rgb_str = explode(',', $rgb_str); - if (count($rgb_str) == 3) { - $reverseColorTable[intval($rgb_str[0])][intval($rgb_str[1])][intval($rgb_str[2])] = $name; + if ( + \count($rgb_str) == 3 && + ! isset($reverseColorTable[\intval($rgb_str[0])][\intval($rgb_str[1])][\intval($rgb_str[2])]) + ) { + $reverseColorTable[\intval($rgb_str[0])][\intval($rgb_str[1])][\intval($rgb_str[2])] = $name; } } } - if (isset($reverseColorTable[intval($r)][intval($g)][intval($b)])) { - return $reverseColorTable[intval($r)][intval($g)][intval($b)]; + if (isset($reverseColorTable[\intval($r)][\intval($g)][\intval($b)])) { + return $reverseColorTable[\intval($r)][\intval($g)][\intval($b)]; } return null; diff --git a/lib/scssphp/scssphp/src/CompilationResult.php b/lib/scssphp/scssphp/src/CompilationResult.php new file mode 100644 index 000000000..36adb0da4 --- /dev/null +++ b/lib/scssphp/scssphp/src/CompilationResult.php @@ -0,0 +1,69 @@ +css = $css; + $this->sourceMap = $sourceMap; + $this->includedFiles = $includedFiles; + } + + /** + * @return string + */ + public function getCss() + { + return $this->css; + } + + /** + * @return string[] + */ + public function getIncludedFiles() + { + return $this->includedFiles; + } + + /** + * The sourceMap content, if it was generated + * + * @return null|string + */ + public function getSourceMap() + { + return $this->sourceMap; + } +} diff --git a/lib/scssphp/scssphp/src/Compiler.php b/lib/scssphp/scssphp/src/Compiler.php index 711d3382f..e414436c8 100644 --- a/lib/scssphp/scssphp/src/Compiler.php +++ b/lib/scssphp/scssphp/src/Compiler.php @@ -1,8 +1,9 @@ + * + * @final Extending the Compiler is deprecated */ class Compiler { + /** + * @deprecated + */ const LINE_COMMENTS = 1; + /** + * @deprecated + */ const DEBUG_INFO = 2; + /** + * @deprecated + */ const WITH_RULE = 1; + /** + * @deprecated + */ const WITH_MEDIA = 2; + /** + * @deprecated + */ const WITH_SUPPORTS = 4; + /** + * @deprecated + */ const WITH_ALL = 7; const SOURCE_MAP_NONE = 0; @@ -71,9 +106,9 @@ class Compiler const SOURCE_MAP_FILE = 2; /** - * @var array + * @var array */ - static protected $operatorNames = [ + protected static $operatorNames = [ '+' => 'add', '-' => 'sub', '*' => 'mul', @@ -87,102 +122,261 @@ class Compiler '<=' => 'lte', '>=' => 'gte', - '<=>' => 'cmp', ]; /** - * @var array + * @var array */ - static protected $namespaces = [ + protected static $namespaces = [ 'special' => '%', 'mixin' => '@', 'function' => '^', ]; - static public $true = [Type::T_KEYWORD, 'true']; - static public $false = [Type::T_KEYWORD, 'false']; - static public $null = [Type::T_NULL]; - static public $nullString = [Type::T_STRING, '', []]; - static public $defaultValue = [Type::T_KEYWORD, '']; - static public $selfSelector = [Type::T_SELF]; - static public $emptyList = [Type::T_LIST, '', []]; - static public $emptyMap = [Type::T_MAP, [], []]; - static public $emptyString = [Type::T_STRING, '"', []]; - static public $with = [Type::T_KEYWORD, 'with']; - static public $without = [Type::T_KEYWORD, 'without']; + public static $true = [Type::T_KEYWORD, 'true']; + public static $false = [Type::T_KEYWORD, 'false']; + /** @deprecated */ + public static $NaN = [Type::T_KEYWORD, 'NaN']; + /** @deprecated */ + public static $Infinity = [Type::T_KEYWORD, 'Infinity']; + public static $null = [Type::T_NULL]; + public static $nullString = [Type::T_STRING, '', []]; + public static $defaultValue = [Type::T_KEYWORD, '']; + public static $selfSelector = [Type::T_SELF]; + public static $emptyList = [Type::T_LIST, '', []]; + public static $emptyMap = [Type::T_MAP, [], []]; + public static $emptyString = [Type::T_STRING, '"', []]; + public static $with = [Type::T_KEYWORD, 'with']; + public static $without = [Type::T_KEYWORD, 'without']; + private static $emptyArgumentList = [Type::T_LIST, '', [], []]; - protected $importPaths = ['']; + /** + * @var array + */ + protected $importPaths = []; + /** + * @var array + */ protected $importCache = []; + + /** + * @var string[] + */ protected $importedFiles = []; + + /** + * @var array + * @phpstan-var array + */ protected $userFunctions = []; + /** + * @var array + */ protected $registeredVars = []; + /** + * @var array + */ protected $registeredFeatures = [ 'extend-selector-pseudoclass' => false, 'at-error' => true, - 'units-level-3' => false, + 'units-level-3' => true, 'global-variable-shadowing' => false, ]; + /** + * @var string|null + */ protected $encoding = null; + /** + * @var null + * @deprecated + */ protected $lineNumberStyle = null; + /** + * @var int|SourceMapGenerator + * @phpstan-var self::SOURCE_MAP_*|SourceMapGenerator + */ protected $sourceMap = self::SOURCE_MAP_NONE; + + /** + * @var array + * @phpstan-var array{sourceRoot?: string, sourceMapFilename?: string|null, sourceMapURL?: string|null, sourceMapWriteTo?: string|null, outputSourceFiles?: bool, sourceMapRootpath?: string, sourceMapBasepath?: string} + */ protected $sourceMapOptions = []; /** - * @var string|\ScssPhp\ScssPhp\Formatter + * @var bool */ - protected $formatter = 'ScssPhp\ScssPhp\Formatter\Nested'; + private $charset = true; + /** + * @var Formatter + */ + protected $formatter; + + /** + * @var string + * @phpstan-var class-string + */ + private $configuredFormatter = Expanded::class; + + /** + * @var Environment + */ protected $rootEnv; + /** + * @var OutputBlock|null + */ protected $rootBlock; /** * @var \ScssPhp\ScssPhp\Compiler\Environment */ protected $env; + /** + * @var OutputBlock|null + */ protected $scope; + /** + * @var Environment|null + */ protected $storeEnv; + /** + * @var bool|null + * + * @deprecated + */ protected $charsetSeen; + /** + * @var array + */ protected $sourceNames; + /** + * @var Cache|null + */ protected $cache; - protected $indentLevel; - protected $extends; - protected $extendsMap; - protected $parsedFiles; - protected $parser; - protected $sourceIndex; - protected $sourceLine; - protected $sourceColumn; - protected $stderr; - protected $shouldEvaluate; - protected $ignoreErrors; + /** + * @var bool + */ + protected $cacheCheckImportResolutions = false; + /** + * @var int + */ + protected $indentLevel; + /** + * @var array[] + */ + protected $extends; + /** + * @var array + */ + protected $extendsMap; + + /** + * @var array + */ + protected $parsedFiles = []; + + /** + * @var Parser|null + */ + protected $parser; + /** + * @var int|null + */ + protected $sourceIndex; + /** + * @var int|null + */ + protected $sourceLine; + /** + * @var int|null + */ + protected $sourceColumn; + /** + * @var bool|null + */ + protected $shouldEvaluate; + /** + * @var null + * @deprecated + */ + protected $ignoreErrors; + /** + * @var bool + */ + protected $ignoreCallStackMessage = false; + + /** + * @var array[] + */ protected $callStack = []; + /** + * @var array + * @phpstan-var list + */ + private $resolvedImports = []; + + /** + * The directory of the currently processed file + * + * @var string|null + */ + private $currentDirectory; + + /** + * The directory of the input file + * + * @var string + */ + private $rootDirectory; + + /** + * @var bool + */ + private $legacyCwdImportPath = true; + + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @var array + */ + private $warnedChildFunctions = []; + /** * Constructor * * @param array|null $cacheOptions + * @phpstan-param array{cacheDir?: string, prefix?: string, forceRefresh?: string, checkImportResolutions?: bool}|null $cacheOptions */ public function __construct($cacheOptions = null) { - $this->parsedFiles = []; $this->sourceNames = []; if ($cacheOptions) { $this->cache = new Cache($cacheOptions); + if (!empty($cacheOptions['checkImportResolutions'])) { + $this->cacheCheckImportResolutions = true; + } } - $this->stderr = fopen('php://stderr', 'w'); + $this->logger = new StreamLogger(fopen('php://stderr', 'w'), true); } /** * Get compiler options * - * @return array + * @return array + * + * @internal */ public function getCompileOptions() { @@ -193,54 +387,97 @@ class Compiler 'encoding' => $this->encoding, 'sourceMap' => serialize($this->sourceMap), 'sourceMapOptions' => $this->sourceMapOptions, - 'formatter' => $this->formatter, + 'formatter' => $this->configuredFormatter, + 'legacyImportPath' => $this->legacyCwdImportPath, ]; return $options; } + /** + * Sets an alternative logger. + * + * Changing the logger in the middle of the compilation is not + * supported and will result in an undefined behavior. + * + * @param LoggerInterface $logger + * + * @return void + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } + /** * Set an alternative error output stream, for testing purpose only * * @param resource $handle + * + * @return void + * + * @deprecated Use {@see setLogger} instead */ public function setErrorOuput($handle) { - $this->stderr = $handle; + @trigger_error('The method "setErrorOuput" is deprecated. Use "setLogger" instead.', E_USER_DEPRECATED); + + $this->logger = new StreamLogger($handle); } /** * Compile scss * - * @api - * - * @param string $code - * @param string $path + * @param string $code + * @param string|null $path * * @return string + * + * @throws SassException when the source fails to compile + * + * @deprecated Use {@see compileString} instead. */ public function compile($code, $path = null) { - if ($this->cache) { - $cacheKey = ($path ? $path : "(stdin)") . ":" . md5($code); - $compileOptions = $this->getCompileOptions(); - $cache = $this->cache->getCache("compile", $cacheKey, $compileOptions); + @trigger_error(sprintf('The "%s" method is deprecated. Use "compileString" instead.', __METHOD__), E_USER_DEPRECATED); - if (is_array($cache) && isset($cache['dependencies']) && isset($cache['out'])) { - // check if any dependency file changed before accepting the cache - foreach ($cache['dependencies'] as $file => $mtime) { - if (! is_file($file) || filemtime($file) !== $mtime) { - unset($cache); - break; - } - } + $result = $this->compileString($code, $path); - if (isset($cache)) { - return $cache['out']; - } + $sourceMap = $result->getSourceMap(); + + if ($sourceMap !== null) { + if ($this->sourceMap instanceof SourceMapGenerator) { + $this->sourceMap->saveMap($sourceMap); + } elseif ($this->sourceMap === self::SOURCE_MAP_FILE) { + $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions); + $sourceMapGenerator->saveMap($sourceMap); } } + return $result->getCss(); + } + + /** + * Compile scss + * + * @param string $source + * @param string|null $path + * + * @return CompilationResult + * + * @throws SassException when the source fails to compile + */ + public function compileString($source, $path = null) + { + if ($this->cache) { + $cacheKey = ($path ? $path : '(stdin)') . ':' . md5($source); + $compileOptions = $this->getCompileOptions(); + $cachedResult = $this->cache->getCache('compile', $cacheKey, $compileOptions); + + if ($cachedResult instanceof CachedResult && $this->isFreshCachedResult($cachedResult)) { + return $cachedResult->getResult(); + } + } $this->indentLevel = -1; $this->extends = []; @@ -251,73 +488,168 @@ class Compiler $this->env = null; $this->scope = null; $this->storeEnv = null; - $this->charsetSeen = null; $this->shouldEvaluate = null; + $this->ignoreCallStackMessage = false; + $this->parsedFiles = []; + $this->importedFiles = []; + $this->resolvedImports = []; - $this->parser = $this->parserFactory($path); - $tree = $this->parser->parse($code); - $this->parser = null; - - $this->formatter = new $this->formatter(); - $this->rootBlock = null; - $this->rootEnv = $this->pushEnv($tree); - - $this->injectVariables($this->registeredVars); - $this->compileRoot($tree); - $this->popEnv(); - - $sourceMapGenerator = null; - - if ($this->sourceMap) { - if (is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) { - $sourceMapGenerator = $this->sourceMap; - $this->sourceMap = self::SOURCE_MAP_FILE; - } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) { - $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions); - } + if (!\is_null($path) && is_file($path)) { + $path = realpath($path) ?: $path; + $this->currentDirectory = dirname($path); + $this->rootDirectory = $this->currentDirectory; + } else { + $this->currentDirectory = null; + $this->rootDirectory = getcwd(); } - $out = $this->formatter->format($this->scope, $sourceMapGenerator); + try { + $this->parser = $this->parserFactory($path); + $tree = $this->parser->parse($source); + $this->parser = null; - if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) { - $sourceMap = $sourceMapGenerator->generateJson(); - $sourceMapUrl = null; + $this->formatter = new $this->configuredFormatter(); + $this->rootBlock = null; + $this->rootEnv = $this->pushEnv($tree); - switch ($this->sourceMap) { - case self::SOURCE_MAP_INLINE: - $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap)); - break; + $warnCallback = function ($message, $deprecation) { + $this->logger->warn($message, $deprecation); + }; + $previousWarnCallback = Warn::setCallback($warnCallback); - case self::SOURCE_MAP_FILE: - $sourceMapUrl = $sourceMapGenerator->saveMap($sourceMap); - break; + try { + $this->injectVariables($this->registeredVars); + $this->compileRoot($tree); + $this->popEnv(); + } finally { + Warn::setCallback($previousWarnCallback); } - $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl); + $sourceMapGenerator = null; + + if ($this->sourceMap) { + if (\is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) { + $sourceMapGenerator = $this->sourceMap; + $this->sourceMap = self::SOURCE_MAP_FILE; + } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) { + $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions); + } + } + assert($this->scope !== null); + + $out = $this->formatter->format($this->scope, $sourceMapGenerator); + + $prefix = ''; + + if ($this->charset && strlen($out) !== Util::mbStrlen($out)) { + $prefix = '@charset "UTF-8";' . "\n"; + $out = $prefix . $out; + } + + $sourceMap = null; + + if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) { + assert($sourceMapGenerator !== null); + $sourceMap = $sourceMapGenerator->generateJson($prefix); + $sourceMapUrl = null; + + switch ($this->sourceMap) { + case self::SOURCE_MAP_INLINE: + $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap)); + break; + + case self::SOURCE_MAP_FILE: + if (isset($this->sourceMapOptions['sourceMapURL'])) { + $sourceMapUrl = $this->sourceMapOptions['sourceMapURL']; + } + break; + } + + if ($sourceMapUrl !== null) { + $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl); + } + } + } catch (SassScriptException $e) { + throw new CompilerException($this->addLocationToMessage($e->getMessage()), 0, $e); } + $includedFiles = []; + + foreach ($this->resolvedImports as $resolvedImport) { + $includedFiles[$resolvedImport['filePath']] = $resolvedImport['filePath']; + } + + $result = new CompilationResult($out, $sourceMap, array_values($includedFiles)); + if ($this->cache && isset($cacheKey) && isset($compileOptions)) { - $v = [ - 'dependencies' => $this->getParsedFiles(), - 'out' => &$out, - ]; - - $this->cache->setCache("compile", $cacheKey, $v, $compileOptions); + $this->cache->setCache('compile', $cacheKey, new CachedResult($result, $this->parsedFiles, $this->resolvedImports), $compileOptions); } - return $out; + // Reset state to free memory + // TODO in 2.0, reset parsedFiles as well when the getter is removed. + $this->resolvedImports = []; + $this->importedFiles = []; + + return $result; + } + + /** + * @param CachedResult $result + * + * @return bool + */ + private function isFreshCachedResult(CachedResult $result) + { + // check if any dependency file changed since the result was compiled + foreach ($result->getParsedFiles() as $file => $mtime) { + if (! is_file($file) || filemtime($file) !== $mtime) { + return false; + } + } + + if ($this->cacheCheckImportResolutions) { + $resolvedImports = []; + + foreach ($result->getResolvedImports() as $import) { + $currentDir = $import['currentDir']; + $path = $import['path']; + // store the check across all the results in memory to avoid multiple findImport() on the same path + // with same context. + // this is happening in a same hit with multiple compilations (especially with big frameworks) + if (empty($resolvedImports[$currentDir][$path])) { + $resolvedImports[$currentDir][$path] = $this->findImport($path, $currentDir); + } + + if ($resolvedImports[$currentDir][$path] !== $import['filePath']) { + return false; + } + } + } + + return true; } /** * Instantiate parser * - * @param string $path + * @param string|null $path * * @return \ScssPhp\ScssPhp\Parser */ protected function parserFactory($path) { - $parser = new Parser($path, count($this->sourceNames), $this->encoding, $this->cache); + // https://sass-lang.com/documentation/at-rules/import + // CSS files imported by Sass don’t allow any special Sass features. + // In order to make sure authors don’t accidentally write Sass in their CSS, + // all Sass features that aren’t also valid CSS will produce errors. + // Otherwise, the CSS will be rendered as-is. It can even be extended! + $cssOnly = false; + + if ($path !== null && substr($path, -4) === '.css') { + $cssOnly = true; + } + + $parser = new Parser($path, \count($this->sourceNames), $this->encoding, $this->cache, $cssOnly, $this->logger); $this->sourceNames[] = $path; $this->addParsedFile($path); @@ -331,12 +663,12 @@ class Compiler * @param array $target * @param array $origin * - * @return boolean + * @return bool */ protected function isSelfExtend($target, $origin) { foreach ($origin as $sel) { - if (in_array($target, $sel)) { + if (\in_array($target, $sel)) { return true; } } @@ -347,17 +679,15 @@ class Compiler /** * Push extends * - * @param array $target + * @param string[] $target * @param array $origin * @param array|null $block + * + * @return void */ protected function pushExtends($target, $origin, $block) { - if ($this->isSelfExtend($target, $origin)) { - return; - } - - $i = count($this->extends); + $i = \count($this->extends); $this->extends[] = [$target, $origin, $block]; foreach ($target as $part) { @@ -372,14 +702,14 @@ class Compiler /** * Make output block * - * @param string $type - * @param array $selectors + * @param string|null $type + * @param string[]|null $selectors * * @return \ScssPhp\ScssPhp\Formatter\OutputBlock */ protected function makeOutputBlock($type, $selectors = null) { - $out = new OutputBlock; + $out = new OutputBlock(); $out->type = $type; $out->lines = []; $out->children = []; @@ -392,9 +722,9 @@ class Compiler $out->sourceLine = $this->env->block->sourceLine; $out->sourceColumn = $this->env->block->sourceColumn; } else { - $out->sourceName = null; - $out->sourceLine = null; - $out->sourceColumn = null; + $out->sourceName = isset($this->sourceNames[$this->sourceIndex]) ? $this->sourceNames[$this->sourceIndex] : '(stdin)'; + $out->sourceLine = $this->sourceLine; + $out->sourceColumn = $this->sourceColumn; } return $out; @@ -404,18 +734,23 @@ class Compiler * Compile root * * @param \ScssPhp\ScssPhp\Block $rootBlock + * + * @return void */ protected function compileRoot(Block $rootBlock) { $this->rootBlock = $this->scope = $this->makeOutputBlock(Type::T_ROOT); $this->compileChildrenNoReturn($rootBlock->children, $this->scope); + assert($this->scope !== null); $this->flattenSelectors($this->scope); $this->missingSelectors(); } /** * Report missing selectors + * + * @return void */ protected function missingSelectors() { @@ -435,7 +770,7 @@ class Compiler $origin = $this->collapseSelectors($origin); $this->sourceLine = $block[Parser::SOURCE_LINE]; - $this->throwError("\"$origin\" failed to @extend \"$target\". The selector \"$target\" was not found."); + throw $this->error("\"$origin\" failed to @extend \"$target\". The selector \"$target\" was not found."); } } @@ -444,6 +779,8 @@ class Compiler * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block * @param string $parentKey + * + * @return void */ protected function flattenSelectors(OutputBlock $block, $parentKey = null) { @@ -453,7 +790,7 @@ class Compiler foreach ($block->selectors as $s) { $selectors[] = $s; - if (! is_array($s)) { + if (! \is_array($s)) { continue; } @@ -486,7 +823,8 @@ class Compiler $block->selectors[] = $this->compileSelector($selector); } - if ($placeholderSelector && 0 === count($block->selectors) && null !== $parentKey) { + if ($placeholderSelector && 0 === \count($block->selectors) && null !== $parentKey) { + assert($block->parent !== null); unset($block->parent->children[$parentKey]); return; @@ -499,7 +837,7 @@ class Compiler } /** - * Glue parts of :not( or :nth-child( ... that are in general splitted in selectors parts + * Glue parts of :not( or :nth-child( ... that are in general split in selectors parts * * @param array $parts * @@ -510,19 +848,20 @@ class Compiler $new = []; foreach ($parts as $part) { - if (is_array($part)) { + if (\is_array($part)) { $part = $this->glueFunctionSelectors($part); $new[] = $part; } else { // a selector part finishing with a ) is the last part of a :not( or :nth-child( // and need to be joined to this - if (count($new) && is_string($new[count($new) - 1]) && - strlen($part) && substr($part, -1) === ')' && strpos($part, '(') === false + if ( + \count($new) && \is_string($new[\count($new) - 1]) && + \strlen($part) && substr($part, -1) === ')' && strpos($part, '(') === false ) { - while (count($new)>1 && substr($new[count($new) - 1], -1) !== '(') { + while (\count($new) > 1 && substr($new[\count($new) - 1], -1) !== '(') { $part = array_pop($new) . $part; } - $new[count($new) - 1] .= $part; + $new[\count($new) - 1] .= $part; } else { $new[] = $part; } @@ -535,21 +874,24 @@ class Compiler /** * Match extends * - * @param array $selector - * @param array $out - * @param integer $from - * @param boolean $initial + * @param array $selector + * @param array $out + * @param int $from + * @param bool $initial + * + * @return void */ protected function matchExtends($selector, &$out, $from = 0, $initial = true) { static $partsPile = []; $selector = $this->glueFunctionSelectors($selector); - if (count($selector) == 1 && in_array(reset($selector), $partsPile)) { + if (\count($selector) == 1 && \in_array(reset($selector), $partsPile)) { return; } $outRecurs = []; + foreach ($selector as $i => $part) { if ($i < $from) { continue; @@ -557,41 +899,43 @@ class Compiler // check that we are not building an infinite loop of extensions // if the new part is just including a previous part don't try to extend anymore - if (count($part) > 1) { + if (\count($part) > 1) { foreach ($partsPile as $previousPart) { - if (! count(array_diff($previousPart, $part))) { + if (! \count(array_diff($previousPart, $part))) { continue 2; } } } $partsPile[] = $part; + if ($this->matchExtendsSingle($part, $origin, $initial)) { - $after = array_slice($selector, $i + 1); - $before = array_slice($selector, 0, $i); + $after = \array_slice($selector, $i + 1); + $before = \array_slice($selector, 0, $i); list($before, $nonBreakableBefore) = $this->extractRelationshipFromFragment($before); foreach ($origin as $new) { $k = 0; // remove shared parts - if (count($new) > 1) { + if (\count($new) > 1) { while ($k < $i && isset($new[$k]) && $selector[$k] === $new[$k]) { $k++; } } - if (count($nonBreakableBefore) and $k == count($new)) { + + if (\count($nonBreakableBefore) && $k === \count($new)) { $k--; } $replacement = []; - $tempReplacement = $k > 0 ? array_slice($new, $k) : $new; + $tempReplacement = $k > 0 ? \array_slice($new, $k) : $new; - for ($l = count($tempReplacement) - 1; $l >= 0; $l--) { + for ($l = \count($tempReplacement) - 1; $l >= 0; $l--) { $slice = []; foreach ($tempReplacement[$l] as $chunk) { - if (! in_array($chunk, $slice)) { + if (! \in_array($chunk, $slice)) { $slice[] = $chunk; } } @@ -603,7 +947,7 @@ class Compiler } } - $afterBefore = $l != 0 ? array_slice($tempReplacement, 0, $l) : []; + $afterBefore = $l != 0 ? \array_slice($tempReplacement, 0, $l) : []; // Merge shared direct relationships. $mergedBefore = $this->mergeDirectRelationships($afterBefore, $nonBreakableBefore); @@ -622,17 +966,18 @@ class Compiler $this->pushOrMergeExtentedSelector($out, $result); // recursively check for more matches - $startRecurseFrom = count($before) + min(count($nonBreakableBefore), count($mergedBefore)); - if (count($origin) > 1) { + $startRecurseFrom = \count($before) + min(\count($nonBreakableBefore), \count($mergedBefore)); + + if (\count($origin) > 1) { $this->matchExtends($result, $out, $startRecurseFrom, false); } else { $this->matchExtends($result, $outRecurs, $startRecurseFrom, false); } // selector sequence merging - if (! empty($before) && count($new) > 1) { - $preSharedParts = $k > 0 ? array_slice($before, 0, $k) : []; - $postSharedParts = $k > 0 ? array_slice($before, $k) : $before; + if (! empty($before) && \count($new) > 1) { + $preSharedParts = $k > 0 ? \array_slice($before, 0, $k) : []; + $postSharedParts = $k > 0 ? \array_slice($before, $k) : $before; list($betweenSharedParts, $nonBreakabl2) = $this->extractRelationshipFromFragment($afterBefore); @@ -652,7 +997,8 @@ class Compiler } array_pop($partsPile); } - while (count($outRecurs)) { + + while (\count($outRecurs)) { $result = array_shift($outRecurs); $this->pushOrMergeExtentedSelector($out, $result); } @@ -660,16 +1006,21 @@ class Compiler /** * Test a part for being a pseudo selector + * * @param string $part - * @param array $matches + * @param array $matches + * * @return bool */ protected function isPseudoSelector($part, &$matches) { - if (strpos($part, ":") === 0 - && preg_match(",^::?([\w-]+)\((.+)\)$,", $part, $matches)) { + if ( + strpos($part, ':') === 0 && + preg_match(",^::?([\w-]+)\((.+)\)$,", $part, $matches) + ) { return true; } + return false; } @@ -679,25 +1030,35 @@ class Compiler * - same as previous * - in a white list * in this case we merge the pseudo selector content + * * @param array $out * @param array $extended + * + * @return void */ protected function pushOrMergeExtentedSelector(&$out, $extended) { - if (count($out) && count($extended) === 1 && count(reset($extended)) === 1) { + if (\count($out) && \count($extended) === 1 && \count(reset($extended)) === 1) { $single = reset($extended); $part = reset($single); - if ($this->isPseudoSelector($part, $matchesExtended) - && in_array($matchesExtended[1], [ 'slotted' ])) { + + if ( + $this->isPseudoSelector($part, $matchesExtended) && + \in_array($matchesExtended[1], [ 'slotted' ]) + ) { $prev = end($out); $prev = $this->glueFunctionSelectors($prev); - if (count($prev) === 1 && count(reset($prev)) === 1) { + + if (\count($prev) === 1 && \count(reset($prev)) === 1) { $single = reset($prev); $part = reset($single); - if ($this->isPseudoSelector($part, $matchesPrev) - && $matchesPrev[1] === $matchesExtended[1]) { + + if ( + $this->isPseudoSelector($part, $matchesPrev) && + $matchesPrev[1] === $matchesExtended[1] + ) { $extended = explode($matchesExtended[1] . '(', $matchesExtended[0], 2); - $extended[1] = $matchesPrev[2] . ", " . $extended[1]; + $extended[1] = $matchesPrev[2] . ', ' . $extended[1]; $extended = implode($matchesExtended[1] . '(', $extended); $extended = [ [ $extended ]]; array_pop($out); @@ -713,9 +1074,9 @@ class Compiler * * @param array $rawSingle * @param array $outOrigin - * @param bool $initial + * @param bool $initial * - * @return boolean + * @return bool */ protected function matchExtendsSingle($rawSingle, &$outOrigin, $initial = true) { @@ -723,18 +1084,18 @@ class Compiler $single = []; // simple usual cases, no need to do the whole trick - if (in_array($rawSingle, [['>'],['+'],['~']])) { + if (\in_array($rawSingle, [['>'],['+'],['~']])) { return false; } foreach ($rawSingle as $part) { // matches Number - if (! is_string($part)) { + if (! \is_string($part)) { return false; } - if (! preg_match('/^[\[.:#%]/', $part) && count($single)) { - $single[count($single) - 1] .= $part; + if (! preg_match('/^[\[.:#%]/', $part) && \count($single)) { + $single[\count($single) - 1] .= $part; } else { $single[] = $part; } @@ -742,7 +1103,7 @@ class Compiler $extendingDecoratedTag = false; - if (count($single) > 1) { + if (\count($single) > 1) { $matches = null; $extendingDecoratedTag = preg_match('/^[a-z0-9]+$/i', $single[0], $matches) ? $matches[0] : false; } @@ -756,24 +1117,31 @@ class Compiler $counts[$idx] = isset($counts[$idx]) ? $counts[$idx] + 1 : 1; } } - if ($initial - && $this->isPseudoSelector($part, $matches) - && ! in_array($matches[1], [ 'not' ])) { + + if ( + $initial && + $this->isPseudoSelector($part, $matches) && + ! \in_array($matches[1], [ 'not' ]) + ) { $buffer = $matches[2]; $parser = $this->parserFactory(__METHOD__); - if ($parser->parseSelector($buffer, $subSelectors)) { + + if ($parser->parseSelector($buffer, $subSelectors, false)) { foreach ($subSelectors as $ksub => $subSelector) { $subExtended = []; $this->matchExtends($subSelector, $subExtended, 0, false); + if ($subExtended) { $subSelectorsExtended = $subSelectors; $subSelectorsExtended[$ksub] = $subExtended; + foreach ($subSelectorsExtended as $ksse => $sse) { $subSelectorsExtended[$ksse] = $this->collapseSelectors($sse); } + $subSelectorsExtended = implode(', ', $subSelectorsExtended); $singleExtended = $single; - $singleExtended[$k] = str_replace("(".$buffer.")", "($subSelectorsExtended)", $part); + $singleExtended[$k] = str_replace('(' . $buffer . ')', "($subSelectorsExtended)", $part); $outOrigin[] = [ $singleExtended ]; $found = true; } @@ -788,7 +1156,7 @@ class Compiler $origin = $this->glueFunctionSelectors($origin); // check count - if ($count !== count($target)) { + if ($count !== \count($target)) { continue; } @@ -798,14 +1166,15 @@ class Compiler foreach ($origin as $j => $new) { // prevent infinite loop when target extends itself - if ($this->isSelfExtend($single, $origin)) { + if ($this->isSelfExtend($single, $origin) && ! $initial) { return false; } $replacement = end($new); // Extending a decorated tag with another tag is not possible. - if ($extendingDecoratedTag && $replacement[0] != $extendingDecoratedTag && + if ( + $extendingDecoratedTag && $replacement[0] != $extendingDecoratedTag && preg_match('/^[a-z0-9]+$/i', $replacement[0]) ) { unset($origin[$j]); @@ -814,8 +1183,8 @@ class Compiler $combined = $this->combineSelectorSingle($replacement, $rem); - if (count(array_diff($combined, $origin[$j][count($origin[$j]) - 1]))) { - $origin[$j][count($origin[$j]) - 1] = $combined; + if (\count(array_diff($combined, $origin[$j][\count($origin[$j]) - 1]))) { + $origin[$j][\count($origin[$j]) - 1] = $combined; } } @@ -844,11 +1213,11 @@ class Compiler $parents = []; $children = []; - $j = $i = count($fragment); + $j = $i = \count($fragment); for (;;) { - $children = $j != $i ? array_slice($fragment, $j, $i - $j) : []; - $parents = array_slice($fragment, 0, $j); + $children = $j != $i ? \array_slice($fragment, $j, $i - $j) : []; + $parents = \array_slice($fragment, 0, $j); $slice = end($parents); if (empty($slice) || ! $this->isImmediateRelationshipCombinator($slice[0])) { @@ -874,8 +1243,15 @@ class Compiler $tag = []; $out = []; $wasTag = false; + $pseudo = []; + + while (\count($other) && strpos(end($other), ':') === 0) { + array_unshift($pseudo, array_pop($other)); + } foreach ([array_reverse($base), array_reverse($other)] as $single) { + $rang = count($single); + foreach ($single as $part) { if (preg_match('/^[\[:]/', $part)) { $out[] = $part; @@ -883,21 +1259,26 @@ class Compiler } elseif (preg_match('/^[\.#]/', $part)) { array_unshift($out, $part); $wasTag = false; - } elseif (preg_match('/^[^_-]/', $part)) { + } elseif (preg_match('/^[^_-]/', $part) && $rang === 1) { $tag[] = $part; $wasTag = true; } elseif ($wasTag) { - $tag[count($tag) - 1] .= $part; + $tag[\count($tag) - 1] .= $part; } else { - $out[] = $part; + array_unshift($out, $part); } + $rang--; } } - if (count($tag)) { + if (\count($tag)) { array_unshift($out, $tag[0]); } + while (\count($pseudo)) { + $out[] = array_shift($pseudo); + } + return $out; } @@ -905,14 +1286,18 @@ class Compiler * Compile media * * @param \ScssPhp\ScssPhp\Block $media + * + * @return void */ protected function compileMedia(Block $media) { + assert($media instanceof MediaBlock); $this->pushEnv($media); $mediaQueries = $this->compileMediaQuery($this->multiplyMedia($this->env)); - if (! empty($mediaQueries) && $mediaQueries) { + if (! empty($mediaQueries)) { + assert($this->scope !== null); $previousScope = $this->scope; $parentScope = $this->mediaParent($this->scope); @@ -929,7 +1314,8 @@ class Compiler foreach ($media->children as $child) { $type = $child[0]; - if ($type !== Type::T_BLOCK && + if ( + $type !== Type::T_BLOCK && $type !== Type::T_MEDIA && $type !== Type::T_DIRECTIVE && $type !== Type::T_IMPORT @@ -940,7 +1326,7 @@ class Compiler } if ($needsWrap) { - $wrapped = new Block; + $wrapped = new Block(); $wrapped->sourceName = $media->sourceName; $wrapped->sourceIndex = $media->sourceIndex; $wrapped->sourceLine = $media->sourceLine; @@ -951,30 +1337,6 @@ class Compiler $wrapped->children = $media->children; $media->children = [[Type::T_BLOCK, $wrapped]]; - - if (isset($this->lineNumberStyle)) { - $annotation = $this->makeOutputBlock(Type::T_COMMENT); - $annotation->depth = 0; - - $file = $this->sourceNames[$media->sourceIndex]; - $line = $media->sourceLine; - - switch ($this->lineNumberStyle) { - case static::LINE_COMMENTS: - $annotation->lines[] = '/* line ' . $line - . ($file ? ', ' . $file : '') - . ' */'; - break; - - case static::DEBUG_INFO: - $annotation->lines[] = '@media -sass-debug-info{' - . ($file ? 'filename{font-family:"' . $file . '"}' : '') - . 'line{font-family:' . $line . '}}'; - break; - } - - $this->scope->children[] = $annotation; - } } $this->compileChildrenNoReturn($media->children, $this->scope); @@ -1008,18 +1370,33 @@ class Compiler /** * Compile directive * - * @param \ScssPhp\ScssPhp\Block|array $block + * @param DirectiveBlock|array $directive * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out + * + * @return void */ protected function compileDirective($directive, OutputBlock $out) { - if (is_array($directive)) { - $s = '@' . $directive[0]; + if (\is_array($directive)) { + $directiveName = $this->compileDirectiveName($directive[0]); + $s = '@' . $directiveName; + if (! empty($directive[1])) { $s .= ' ' . $this->compileValue($directive[1]); } - $this->appendRootDirective($s . ';', $out); + // sass-spec compliance on newline after directives, a bit tricky :/ + $appendNewLine = (! empty($directive[2]) || strpos($s, "\n")) ? "\n" : ""; + if (\is_array($directive[0]) && empty($directive[1])) { + $appendNewLine = "\n"; + } + + if (empty($directive[3])) { + $this->appendRootDirective($s . ';' . $appendNewLine, $out, [Type::T_COMMENT, Type::T_DIRECTIVE]); + } else { + $this->appendOutputLine($out, Type::T_DIRECTIVE, $s . ';'); + } } else { + $directive->name = $this->compileDirectiveName($directive->name); $s = '@' . $directive->name; if (! empty($directive->value)) { @@ -1034,20 +1411,39 @@ class Compiler } } + /** + * directive names can include some interpolation + * + * @param string|array $directiveName + * @return string + * @throws CompilerException + */ + protected function compileDirectiveName($directiveName) + { + if (is_string($directiveName)) { + return $directiveName; + } + + return $this->compileValue($directiveName); + } + /** * Compile at-root * * @param \ScssPhp\ScssPhp\Block $block + * + * @return void */ protected function compileAtRoot(Block $block) { + assert($block instanceof AtRootBlock); $env = $this->pushEnv($block); $envs = $this->compactEnv($env); list($with, $without) = $this->compileWith(isset($block->with) ? $block->with : null); // wrap inline selector if ($block->selector) { - $wrapped = new Block; + $wrapped = new Block(); $wrapped->sourceName = $block->sourceName; $wrapped->sourceIndex = $block->sourceIndex; $wrapped->sourceLine = $block->sourceLine; @@ -1063,8 +1459,11 @@ class Compiler } $selfParent = $block->selfParent; + assert($selfParent !== null, 'at-root blocks must have a selfParent set.'); - if (! $block->selfParent->selectors && isset($block->parent) && $block->parent && + if ( + ! $selfParent->selectors && + isset($block->parent) && isset($block->parent->selectors) && $block->parent->selectors ) { $selfParent = $block->parent; @@ -1072,13 +1471,15 @@ class Compiler $this->env = $this->filterWithWithout($envs, $with, $without); + assert($this->scope !== null); $saveScope = $this->scope; $this->scope = $this->filterScopeWithWithout($saveScope, $with, $without); // propagate selfParent to the children where they still can be useful $this->compileChildrenNoReturn($block->children, $this->scope, $selfParent); - $this->scope = $this->completeScope($this->scope, $saveScope); + assert($this->scope !== null); + $this->completeScope($this->scope, $saveScope); $this->scope = $saveScope; $this->env = $this->extractEnv($envs); @@ -1086,25 +1487,26 @@ class Compiler } /** - * Filter at-root scope depending of with/without option + * Filter at-root scope depending on with/without option * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope * @param array $with * @param array $without * - * @return mixed + * @return OutputBlock */ protected function filterScopeWithWithout($scope, $with, $without) { $filteredScopes = []; $childStash = []; - if ($scope->type === TYPE::T_ROOT) { + if ($scope->type === Type::T_ROOT) { return $scope; } + assert($this->rootBlock !== null); // start from the root - while ($scope->parent && $scope->parent->type !== TYPE::T_ROOT) { + while ($scope->parent && $scope->parent->type !== Type::T_ROOT) { array_unshift($childStash, $scope); $scope = $scope->parent; } @@ -1127,7 +1529,7 @@ class Compiler $filteredScopes[] = $s; } - if (count($childStash)) { + if (\count($childStash)) { $scope = array_shift($childStash); } elseif ($scope->children) { $scope = end($scope->children); @@ -1136,7 +1538,7 @@ class Compiler } } - if (! count($filteredScopes)) { + if (! \count($filteredScopes)) { return $this->rootBlock; } @@ -1147,7 +1549,7 @@ class Compiler $p = &$newScope; - while (count($filteredScopes)) { + while (\count($filteredScopes)) { $s = array_shift($filteredScopes); $s->parent = $p; $p->children[] = $s; @@ -1165,11 +1567,11 @@ class Compiler * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $previousScope * - * @return mixed + * @return OutputBlock */ protected function completeScope($scope, $previousScope) { - if (! $scope->type && (! $scope->selectors || ! count($scope->selectors)) && count($scope->lines)) { + if (! $scope->type && ! $scope->selectors && \count($scope->lines)) { $scope->selectors = $this->findScopeSelectors($previousScope, $scope->depth); } @@ -1186,7 +1588,7 @@ class Compiler * Find a selector by the depth node in the scope * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope - * @param integer $depth + * @param int $depth * * @return array */ @@ -1210,9 +1612,11 @@ class Compiler /** * Compile @at-root's with: inclusion / without: exclusion into 2 lists uses to filter scope/env later * - * @param array $withCondition + * @param array|null $withCondition * * @return array + * + * @phpstan-return array{array, array} */ protected function compileWith($withCondition) { @@ -1221,9 +1625,21 @@ class Compiler $without = ['rule' => true]; if ($withCondition) { - if ($this->libMapHasKey([$withCondition, static::$with])) { + if ($withCondition[0] === Type::T_INTERPOLATE) { + $w = $this->compileValue($withCondition); + + $buffer = "($w)"; + $parser = $this->parserFactory(__METHOD__); + + if ($parser->parseValue($buffer, $reParsedWith)) { + $withCondition = $reParsedWith; + } + } + + $withConfig = $this->mapGet($withCondition, static::$with); + if ($withConfig !== null) { $without = []; // cancel the default - $list = $this->coerceList($this->libMapGet([$withCondition, static::$with])); + $list = $this->coerceList($withConfig); foreach ($list[2] as $item) { $keyword = $this->compileStringContent($this->coerceString($item)); @@ -1232,9 +1648,10 @@ class Compiler } } - if ($this->libMapHasKey([$withCondition, static::$without])) { + $withoutConfig = $this->mapGet($withCondition, static::$without); + if ($withoutConfig !== null) { $without = []; // cancel the default - $list = $this->coerceList($this->libMapGet([$withCondition, static::$without])); + $list = $this->coerceList($withoutConfig); foreach ($list[2] as $item) { $keyword = $this->compileStringContent($this->coerceString($item)); @@ -1250,11 +1667,13 @@ class Compiler /** * Filter env stack * - * @param array $envs + * @param Environment[] $envs * @param array $with * @param array $without * - * @return \ScssPhp\ScssPhp\Compiler\Environment + * @return Environment + * + * @phpstan-param non-empty-array $envs */ protected function filterWithWithout($envs, $with, $without) { @@ -1282,7 +1701,7 @@ class Compiler * @param array $with * @param array $without * - * @return boolean + * @return bool */ protected function isWith($block, $with, $without) { @@ -1292,8 +1711,9 @@ class Compiler } if ($block->type === Type::T_DIRECTIVE) { + assert($block instanceof DirectiveBlock || $block instanceof OutputBlock); if (isset($block->name)) { - return $this->testWithWithout($block->name, $with, $without); + return $this->testWithWithout($this->compileDirectiveName($block->name), $with, $without); } elseif (isset($block->selectors) && preg_match(',@(\w+),ims', json_encode($block->selectors), $m)) { return $this->testWithWithout($m[1], $with, $without); } else { @@ -1302,14 +1722,14 @@ class Compiler } } elseif (isset($block->selectors)) { // a selector starting with number is a keyframe rule - if (count($block->selectors)) { + if (\count($block->selectors)) { $s = reset($block->selectors); - while (is_array($s)) { + while (\is_array($s)) { $s = reset($s); } - if (is_object($s) && $s instanceof Node\Number) { + if (\is_object($s) && $s instanceof Number) { return $this->testWithWithout('keyframes', $with, $without); } } @@ -1327,14 +1747,13 @@ class Compiler * @param array $with * @param array $without * - * @return boolean + * @return bool * true if the block should be kept, false to reject */ protected function testWithWithout($what, $with, $without) { - // if without, reject only if in the list (or 'all' is in the list) - if (count($without)) { + if (\count($without)) { return (isset($without[$what]) || isset($without['all'])) ? false : true; } @@ -1347,7 +1766,9 @@ class Compiler * Compile keyframe block * * @param \ScssPhp\ScssPhp\Block $block - * @param array $selectors + * @param string[] $selectors + * + * @return void */ protected function compileKeyframeBlock(Block $block, $selectors) { @@ -1361,10 +1782,12 @@ class Compiler $this->scope = $this->makeOutputBlock($block->type, $selectors); $this->scope->depth = 1; + assert($this->scope->parent !== null); $this->scope->parent->children[] = $this->scope; $this->compileChildrenNoReturn($block->children, $this->scope); + assert($this->scope !== null); $this->scope = $this->scope->parent; $this->env = $this->extractEnv($envs); @@ -1374,11 +1797,14 @@ class Compiler /** * Compile nested properties lines * - * @param \ScssPhp\ScssPhp\Block $block - * @param OutputBlock $out + * @param \ScssPhp\ScssPhp\Block $block + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out + * + * @return void */ protected function compileNestedPropertiesBlock(Block $block, OutputBlock $out) { + assert($block instanceof NestedPropertyBlock); $prefix = $this->compileValue($block->prefix) . '-'; $nested = $this->makeOutputBlock($block->type); @@ -1397,6 +1823,7 @@ class Compiler break; case Type::T_NESTED_PROPERTY: + assert($child[1] instanceof NestedPropertyBlock); array_unshift($child[1]->prefix[2], $prefix); break; } @@ -1409,18 +1836,21 @@ class Compiler * Compile nested block * * @param \ScssPhp\ScssPhp\Block $block - * @param array $selectors + * @param string[] $selectors + * + * @return void */ protected function compileNestedBlock(Block $block, $selectors) { $this->pushEnv($block); $this->scope = $this->makeOutputBlock($block->type, $selectors); + assert($this->scope->parent !== null); $this->scope->parent->children[] = $this->scope; // wrap assign children in a block // except for @font-face - if ($block->type !== Type::T_DIRECTIVE || $block->name !== "font-face") { + if (!$block instanceof DirectiveBlock || $this->compileDirectiveName($block->name) !== 'font-face') { // need wrapping? $needWrapping = false; @@ -1432,7 +1862,7 @@ class Compiler } if ($needWrapping) { - $wrapped = new Block; + $wrapped = new Block(); $wrapped->sourceName = $block->sourceName; $wrapped->sourceIndex = $block->sourceIndex; $wrapped->sourceLine = $block->sourceLine; @@ -1449,6 +1879,7 @@ class Compiler $this->compileChildrenNoReturn($block->children, $this->scope); + assert($this->scope !== null); $this->scope = $this->scope->parent; $this->popEnv(); @@ -1471,41 +1902,21 @@ class Compiler * @see Compiler::compileChild() * * @param \ScssPhp\ScssPhp\Block $block + * + * @return void */ protected function compileBlock(Block $block) { $env = $this->pushEnv($block); + assert($block->selectors !== null); $env->selectors = $this->evalSelectors($block->selectors); $out = $this->makeOutputBlock(null); - if (isset($this->lineNumberStyle) && count($env->selectors) && count($block->children)) { - $annotation = $this->makeOutputBlock(Type::T_COMMENT); - $annotation->depth = 0; - - $file = $this->sourceNames[$block->sourceIndex]; - $line = $block->sourceLine; - - switch ($this->lineNumberStyle) { - case static::LINE_COMMENTS: - $annotation->lines[] = '/* line ' . $line - . ($file ? ', ' . $file : '') - . ' */'; - break; - - case static::DEBUG_INFO: - $annotation->lines[] = '@media -sass-debug-info{' - . ($file ? 'filename{font-family:"' . $file . '"}' : '') - . 'line{font-family:' . $line . '}}'; - break; - } - - $this->scope->children[] = $annotation; - } - + assert($this->scope !== null); $this->scope->children[] = $out; - if (count($block->children)) { + if (\count($block->children)) { $out->selectors = $this->multiplySelectors($env, $block->selfParent); // propagate selfParent to the children where they still can be useful @@ -1520,6 +1931,7 @@ class Compiler // and revert for the following children of the same block if ($selfParentSelectors) { + assert($block->selfParent !== null); $block->selfParent->selectors = $selfParentSelectors; } } @@ -1531,10 +1943,10 @@ class Compiler /** * Compile the value of a comment that can have interpolation * - * @param array $value - * @param boolean $pushEnv + * @param array $value + * @param bool $pushEnv * - * @return array|mixed|string + * @return string */ protected function compileCommentValue($value, $pushEnv = false) { @@ -1543,18 +1955,19 @@ class Compiler if (isset($value[2])) { if ($pushEnv) { $this->pushEnv(); - $storeEnv = $this->storeEnv; - $this->storeEnv = $this->env; } try { $c = $this->compileValue($value[2]); - } catch (\Exception $e) { + } catch (SassScriptException $e) { + $this->logger->warn('Ignoring interpolation errors in multiline comments is deprecated and will be removed in ScssPhp 2.0. ' . $this->addLocationToMessage($e->getMessage()), true); + // ignore error in comment compilation which are only interpolation + } catch (SassException $e) { + $this->logger->warn('Ignoring interpolation errors in multiline comments is deprecated and will be removed in ScssPhp 2.0. ' . $e->getMessage(), true); // ignore error in comment compilation which are only interpolation } if ($pushEnv) { - $this->storeEnv = $storeEnv; $this->popEnv(); } } @@ -1566,12 +1979,15 @@ class Compiler * Compile root level comment * * @param array $block + * + * @return void */ protected function compileComment($block) { $out = $this->makeOutputBlock(Type::T_COMMENT); $out->lines[] = $this->compileCommentValue($block, true); + assert($this->scope !== null); $this->scope->children[] = $out; } @@ -1586,15 +2002,25 @@ class Compiler { $this->shouldEvaluate = false; - $selectors = array_map([$this, 'evalSelector'], $selectors); + $evaluatedSelectors = []; + foreach ($selectors as $selector) { + $evaluatedSelectors[] = $this->evalSelector($selector); + } + $selectors = $evaluatedSelectors; // after evaluating interpolates, we might need a second pass if ($this->shouldEvaluate) { - $selectors = $this->revertSelfSelector($selectors); + $selectors = $this->replaceSelfSelector($selectors, '&'); $buffer = $this->collapseSelectors($selectors); $parser = $this->parserFactory(__METHOD__); - if ($parser->parseSelector($buffer, $newSelectors)) { + try { + $isValid = $parser->parseSelector($buffer, $newSelectors, true); + } catch (ParserException $e) { + throw $this->error($e->getMessage()); + } + + if ($isValid) { $selectors = array_map([$this, 'evalSelector'], $newSelectors); } } @@ -1608,6 +2034,8 @@ class Compiler * @param array $selector * * @return array + * + * @phpstan-impure */ protected function evalSelector($selector) { @@ -1620,20 +2048,23 @@ class Compiler * @param array $part * * @return array + * + * @phpstan-impure */ protected function evalSelectorPart($part) { foreach ($part as &$p) { - if (is_array($p) && ($p[0] === Type::T_INTERPOLATE || $p[0] === Type::T_STRING)) { + if (\is_array($p) && ($p[0] === Type::T_INTERPOLATE || $p[0] === Type::T_STRING)) { $p = $this->compileValue($p); - // force re-evaluation - if (strpos($p, '&') !== false || strpos($p, ',') !== false) { + // force re-evaluation if self char or non standard char + if (preg_match(',[^\w-],', $p)) { $this->shouldEvaluate = true; } - } elseif (is_string($p) && strlen($p) >= 2 && - ($first = $p[0]) && ($first === '"' || $first === "'") && - substr($p, -1) === $first + } elseif ( + \is_string($p) && \strlen($p) >= 2 && + ($p[0] === '"' || $p[0] === "'") && + substr($p, -1) === $p[0] ) { $p = substr($p, 1, -1); } @@ -1645,14 +2076,44 @@ class Compiler /** * Collapse selectors * - * @param array $selectors - * @param boolean $selectorFormat - * if false return a collapsed string - * if true return an array description of a structured selector + * @param array $selectors * * @return string */ - protected function collapseSelectors($selectors, $selectorFormat = false) + protected function collapseSelectors($selectors) + { + $parts = []; + + foreach ($selectors as $selector) { + $output = []; + + foreach ($selector as $node) { + $compound = ''; + + array_walk_recursive( + $node, + function ($value, $key) use (&$compound) { + $compound .= $value; + } + ); + + $output[] = $compound; + } + + $parts[] = implode(' ', $output); + } + + return implode(', ', $parts); + } + + /** + * Collapse selectors + * + * @param array $selectors + * + * @return array + */ + private function collapseSelectorsAsList($selectors) { $parts = []; @@ -1670,59 +2131,52 @@ class Compiler } ); - if ($selectorFormat && $this->isImmediateRelationshipCombinator($compound)) { - if (count($output)) { - $output[count($output) - 1] .= ' ' . $compound; + if ($this->isImmediateRelationshipCombinator($compound)) { + if (\count($output)) { + $output[\count($output) - 1] .= ' ' . $compound; } else { $output[] = $compound; } $glueNext = true; } elseif ($glueNext) { - $output[count($output) - 1] .= ' ' . $compound; + $output[\count($output) - 1] .= ' ' . $compound; $glueNext = false; } else { $output[] = $compound; } } - if ($selectorFormat) { - foreach ($output as &$o) { - $o = [Type::T_STRING, '', [$o]]; - } - - $output = [Type::T_LIST, ' ', $output]; - } else { - $output = implode(' ', $output); + foreach ($output as &$o) { + $o = [Type::T_STRING, '', [$o]]; } - $parts[] = $output; + $parts[] = [Type::T_LIST, ' ', $output]; } - if ($selectorFormat) { - $parts = [Type::T_LIST, ',', $parts]; - } else { - $parts = implode(', ', $parts); - } - - return $parts; + return [Type::T_LIST, ',', $parts]; } /** * Parse down the selector and revert [self] to "&" before a reparsing * - * @param array $selectors + * @param array $selectors + * @param string|null $replace * * @return array */ - protected function revertSelfSelector($selectors) + protected function replaceSelfSelector($selectors, $replace = null) { foreach ($selectors as &$part) { - if (is_array($part)) { + if (\is_array($part)) { if ($part === [Type::T_SELF]) { - $part = '&'; + if (\is_null($replace)) { + $replace = $this->reduce([Type::T_SELF]); + $replace = $this->compileValue($replace); + } + $part = $replace; } else { - $part = $this->revertSelfSelector($part); + $part = $this->replaceSelfSelector($part, $replace); } } } @@ -1742,18 +2196,19 @@ class Compiler $joined = []; foreach ($single as $part) { - if (empty($joined) || - ! is_string($part) || + if ( + empty($joined) || + ! \is_string($part) || preg_match('/[\[.:#%]/', $part) ) { $joined[] = $part; continue; } - if (is_array(end($joined))) { + if (\is_array(end($joined))) { $joined[] = $part; } else { - $joined[count($joined) - 1] .= $part; + $joined[\count($joined) - 1] .= $part; } } @@ -1769,7 +2224,7 @@ class Compiler */ protected function compileSelector($selector) { - if (! is_array($selector)) { + if (! \is_array($selector)) { return $selector; // media and the like } @@ -1792,7 +2247,7 @@ class Compiler protected function compileSelectorPart($piece) { foreach ($piece as &$p) { - if (! is_array($p)) { + if (! \is_array($p)) { continue; } @@ -1815,17 +2270,17 @@ class Compiler * * @param array $selector * - * @return boolean + * @return bool */ protected function hasSelectorPlaceholder($selector) { - if (! is_array($selector)) { + if (! \is_array($selector)) { return false; } foreach ($selector as $parts) { foreach ($parts as $part) { - if (strlen($part) && '%' === $part[0]) { + if (\strlen($part) && '%' === $part[0]) { return true; } } @@ -1834,6 +2289,11 @@ class Compiler return false; } + /** + * @param string $name + * + * @return void + */ protected function pushCallStack($name = '') { $this->callStack[] = [ @@ -1844,15 +2304,18 @@ class Compiler ]; // infinite calling loop - if (count($this->callStack) > 25000) { + if (\count($this->callStack) > 25000) { // not displayed but you can var_dump it to deep debug $msg = $this->callStackMessage(true, 100); - $msg = "Infinite calling loop"; + $msg = 'Infinite calling loop'; - $this->throwError($msg); + throw $this->error($msg); } } + /** + * @return void + */ protected function popCallStack() { array_pop($this->callStack); @@ -1865,7 +2328,7 @@ class Compiler * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out * @param string $traceName * - * @return array|null + * @return array|Number|null */ protected function compileChildren($stms, OutputBlock $out, $traceName = '') { @@ -1875,6 +2338,8 @@ class Compiler $ret = $this->compileChild($stm, $out); if (isset($ret)) { + $this->popCallStack(); + return $ret; } } @@ -1885,13 +2350,15 @@ class Compiler } /** - * Compile children and throw exception if unexpected @return + * Compile children and throw exception if unexpected `@return` * * @param array $stms * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out * @param \ScssPhp\ScssPhp\Block $selfParent * @param string $traceName * + * @return void + * * @throws \Exception */ protected function compileChildrenNoReturn($stms, OutputBlock $out, $selfParent = null, $traceName = '') @@ -1899,11 +2366,11 @@ class Compiler $this->pushCallStack($traceName); foreach ($stms as $stm) { - if ($selfParent && isset($stm[1]) && is_object($stm[1]) && $stm[1] instanceof Block) { + if ($selfParent && isset($stm[1]) && \is_object($stm[1]) && $stm[1] instanceof Block) { $stm[1]->selfParent = $selfParent; $ret = $this->compileChild($stm, $out); $stm[1]->selfParent = null; - } elseif ($selfParent && in_array($stm[0], [TYPE::T_INCLUDE, TYPE::T_EXTEND])) { + } elseif ($selfParent && \in_array($stm[0], [Type::T_INCLUDE, Type::T_EXTEND])) { $stm['selfParent'] = $selfParent; $ret = $this->compileChild($stm, $out); unset($stm['selfParent']); @@ -1912,9 +2379,7 @@ class Compiler } if (isset($ret)) { - $this->throwError('@return may only be used within a function'); - - return; + throw $this->error('@return may only be used within a function'); } } @@ -1923,7 +2388,7 @@ class Compiler /** - * evaluate media query : compile internal value keeping the structure inchanged + * evaluate media query : compile internal value keeping the structure unchanged * * @param array $queryList * @@ -1939,12 +2404,13 @@ class Compiler $shouldReparse = false; foreach ($query as $kq => $q) { - for ($i = 1; $i < count($q); $i++) { + for ($i = 1; $i < \count($q); $i++) { $value = $this->compileValue($q[$i]); // the parser had no mean to know if media type or expression if it was an interpolation // so you need to reparse if the T_MEDIA_TYPE looks like anything else a media type - if ($q[0] == Type::T_MEDIA_TYPE && + if ( + $q[0] == Type::T_MEDIA_TYPE && (strpos($value, '(') !== false || strpos($value, ')') !== false || strpos($value, ':') !== false || @@ -1958,21 +2424,21 @@ class Compiler } if ($shouldReparse) { - if (is_null($parser)) { + if (\is_null($parser)) { $parser = $this->parserFactory(__METHOD__); } $queryString = $this->compileMediaQuery([$queryList[$kql]]); $queryString = reset($queryString); - if (strpos($queryString, '@media ') === 0) { + if ($queryString !== false && strpos($queryString, '@media ') === 0) { $queryString = substr($queryString, 7); $queries = []; if ($parser->parseMediaQueryList($queryString, $queries)) { $queries = $this->evaluateMediaQuery($queries[2]); - while (count($queries)) { + while (\count($queries)) { $outQueryList[] = array_shift($queries); } @@ -1992,14 +2458,14 @@ class Compiler * * @param array $queryList * - * @return array + * @return string[] */ protected function compileMediaQuery($queryList) { $start = '@media '; $default = trim($start); $out = []; - $current = ""; + $current = ''; foreach ($queryList as $query) { $type = null; @@ -2017,17 +2483,17 @@ class Compiler foreach ($query as $q) { switch ($q[0]) { case Type::T_MEDIA_TYPE: - $newType = array_map([$this, 'compileValue'], array_slice($q, 1)); + $newType = array_map([$this, 'compileValue'], \array_slice($q, 1)); // combining not and anything else than media type is too risky and should be avoided if (! $mediaTypeOnly) { - if (in_array(Type::T_NOT, $newType) || ($type && in_array(Type::T_NOT, $type) )) { + if (\in_array(Type::T_NOT, $newType) || ($type && \in_array(Type::T_NOT, $type) )) { if ($type) { array_unshift($parts, implode(' ', array_filter($type))); } if (! empty($parts)) { - if (strlen($current)) { + if (\strlen($current)) { $current .= $this->formatter->tagSeparator; } @@ -2038,7 +2504,7 @@ class Compiler $out[] = $start . $current; } - $current = ""; + $current = ''; $type = null; $parts = []; } @@ -2090,7 +2556,7 @@ class Compiler } if (! empty($parts)) { - if (strlen($current)) { + if (\strlen($current)) { $current .= $this->formatter->tagSeparator; } @@ -2172,7 +2638,7 @@ class Compiler return $type1; } - if (count($type1) > 1) { + if (\count($type1) > 1) { $m1 = strtolower($type1[0]); $t1 = strtolower($type1[1]); } else { @@ -2180,7 +2646,7 @@ class Compiler $t1 = strtolower($type1[0]); } - if (count($type2) > 1) { + if (\count($type2) > 1) { $m2 = strtolower($type2[0]); $t2 = strtolower($type2[1]); } else { @@ -2213,7 +2679,7 @@ class Compiler } // t1 == t2, neither m1 nor m2 are "not" - return [empty($m1)? $m2 : $m1, $t1]; + return [empty($m1) ? $m2 : $m1, $t1]; } /** @@ -2221,38 +2687,40 @@ class Compiler * * @param array $rawPath * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * @param boolean $once + * @param bool $once * - * @return boolean + * @return bool */ protected function compileImport($rawPath, OutputBlock $out, $once = false) { if ($rawPath[0] === Type::T_STRING) { $path = $this->compileStringContent($rawPath); - if ($path = $this->findImport($path)) { - if (! $once || ! in_array($path, $this->importedFiles)) { - $this->importFile($path, $out); - $this->importedFiles[] = $path; + if (strpos($path, 'url(') !== 0 && $filePath = $this->findImport($path, $this->currentDirectory)) { + $this->registerImport($this->currentDirectory, $path, $filePath); + + if (! $once || ! \in_array($filePath, $this->importedFiles)) { + $this->importFile($filePath, $out); + $this->importedFiles[] = $filePath; } return true; } - $this->appendRootDirective('@import ' . $this->compileValue($rawPath). ';', $out); + $this->appendRootDirective('@import ' . $this->compileImportPath($rawPath) . ';', $out); return false; } if ($rawPath[0] === Type::T_LIST) { // handle a list of strings - if (count($rawPath[2]) === 0) { + if (\count($rawPath[2]) === 0) { return false; } foreach ($rawPath[2] as $path) { if ($path[0] !== Type::T_STRING) { - $this->appendRootDirective('@import ' . $this->compileValue($rawPath) . ';', $out); + $this->appendRootDirective('@import ' . $this->compileImportPath($rawPath) . ';', $out); return false; } @@ -2265,19 +2733,68 @@ class Compiler return true; } - $this->appendRootDirective('@import ' . $this->compileValue($rawPath) . ';', $out); + $this->appendRootDirective('@import ' . $this->compileImportPath($rawPath) . ';', $out); return false; } + /** + * @param array $rawPath + * @return string + * @throws CompilerException + */ + protected function compileImportPath($rawPath) + { + $path = $this->compileValue($rawPath); + + // case url() without quotes : suppress \r \n remaining in the path + // if this is a real string there can not be CR or LF char + if (strpos($path, 'url(') === 0) { + $path = str_replace(array("\r", "\n"), array('', ' '), $path); + } else { + // if this is a file name in a string, spaces should be escaped + $path = $this->reduce($rawPath); + $path = $this->escapeImportPathString($path); + $path = $this->compileValue($path); + } + + return $path; + } + + /** + * @param array $path + * @return array + * @throws CompilerException + */ + protected function escapeImportPathString($path) + { + switch ($path[0]) { + case Type::T_LIST: + foreach ($path[2] as $k => $v) { + $path[2][$k] = $this->escapeImportPathString($v); + } + break; + case Type::T_STRING: + if ($path[1]) { + $path = $this->compileValue($path); + $path = str_replace(' ', '\\ ', $path); + $path = [Type::T_KEYWORD, $path]; + } + break; + } + + return $path; + } /** * Append a root directive like @import or @charset as near as the possible from the source code * (keeping before comments, @import and @charset coming before in the source code) * - * @param string $line - * @param @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * @param array $allowed + * @param string $line + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out + * @param array $allowed + * + * @return void */ protected function appendRootDirective($line, $out, $allowed = [Type::T_COMMENT]) { @@ -2289,8 +2806,8 @@ class Compiler $i = 0; - while ($i < count($root->children)) { - if (! isset($root->children[$i]->type) || ! in_array($root->children[$i]->type, $allowed)) { + while ($i < \count($root->children)) { + if (! isset($root->children[$i]->type) || ! \in_array($root->children[$i]->type, $allowed)) { break; } @@ -2300,21 +2817,21 @@ class Compiler // remove incompatible children from the bottom of the list $saveChildren = []; - while ($i < count($root->children)) { + while ($i < \count($root->children)) { $saveChildren[] = array_pop($root->children); } // insert the directive as a comment $child = $this->makeOutputBlock(Type::T_COMMENT); $child->lines[] = $line; - $child->sourceName = $this->sourceNames[$this->sourceIndex]; + $child->sourceName = $this->sourceNames[$this->sourceIndex] ?: '(stdin)'; $child->sourceLine = $this->sourceLine; $child->sourceColumn = $this->sourceColumn; $root->children[] = $child; // repush children - while (count($saveChildren)) { + while (\count($saveChildren)) { $root->children[] = array_pop($saveChildren); } } @@ -2325,25 +2842,23 @@ class Compiler * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out * @param string $type - * @param string|mixed $line + * @param string $line + * + * @return void */ protected function appendOutputLine(OutputBlock $out, $type, $line) { $outWrite = &$out; - if ($type === Type::T_COMMENT) { - $parent = $out->parent; - - if (end($parent->children) !== $out) { - $outWrite = &$parent->children[count($parent->children) - 1]; - } - } - // check if it's a flat output or not - if (count($out->children)) { - $lastChild = &$out->children[count($out->children) - 1]; + if (\count($out->children)) { + $lastChild = &$out->children[\count($out->children) - 1]; - if ($lastChild->depth === $out->depth && is_null($lastChild->selectors) && ! count($lastChild->children)) { + if ( + $lastChild->depth === $out->depth && + \is_null($lastChild->selectors) && + ! \count($lastChild->children) + ) { $outWrite = $lastChild; } else { $nextLines = $this->makeOutputBlock($type); @@ -2364,7 +2879,7 @@ class Compiler * @param array $child * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out * - * @return array + * @return array|Number|null */ protected function compileChild($child, OutputBlock $out) { @@ -2372,18 +2887,19 @@ class Compiler $this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null; $this->sourceLine = isset($child[Parser::SOURCE_LINE]) ? $child[Parser::SOURCE_LINE] : -1; $this->sourceColumn = isset($child[Parser::SOURCE_COLUMN]) ? $child[Parser::SOURCE_COLUMN] : -1; - } elseif (is_array($child) && isset($child[1]->sourceLine)) { + } elseif (\is_array($child) && isset($child[1]->sourceLine) && $child[1] instanceof Block) { $this->sourceIndex = $child[1]->sourceIndex; $this->sourceLine = $child[1]->sourceLine; $this->sourceColumn = $child[1]->sourceColumn; } elseif (! empty($out->sourceLine) && ! empty($out->sourceName)) { $this->sourceLine = $out->sourceLine; - $this->sourceIndex = array_search($out->sourceName, $this->sourceNames); + $sourceIndex = array_search($out->sourceName, $this->sourceNames); $this->sourceColumn = $out->sourceColumn; - if ($this->sourceIndex === false) { - $this->sourceIndex = null; + if ($sourceIndex === false) { + $sourceIndex = null; } + $this->sourceIndex = $sourceIndex; } switch ($child[0]) { @@ -2416,10 +2932,30 @@ class Compiler break; case Type::T_CHARSET: - if (! $this->charsetSeen) { - $this->charsetSeen = true; - $this->appendRootDirective('@charset ' . $this->compileValue($child[1]) . ';', $out); + break; + + case Type::T_CUSTOM_PROPERTY: + list(, $name, $value) = $child; + $compiledName = $this->compileValue($name); + + // if the value reduces to null from something else then + // the property should be discarded + if ($value[0] !== Type::T_NULL) { + $value = $this->reduce($value); + + if ($value[0] === Type::T_NULL || $value === static::$nullString) { + break; + } } + + $compiledValue = $this->compileValue($value); + + $line = $this->formatter->customProperty( + $compiledName, + $compiledValue + ); + + $this->appendOutputLine($out, Type::T_ASSIGN, $line); break; case Type::T_ASSIGN: @@ -2427,8 +2963,8 @@ class Compiler if ($name[0] === Type::T_VARIABLE) { $flags = isset($child[3]) ? $child[3] : []; - $isDefault = in_array('!default', $flags); - $isGlobal = in_array('!global', $flags); + $isDefault = \in_array('!default', $flags); + $isGlobal = \in_array('!global', $flags); if ($isGlobal) { $this->set($name[1], $this->reduce($value), false, $this->rootEnv, $value); @@ -2436,7 +2972,7 @@ class Compiler } $shouldSet = $isDefault && - (is_null($result = $this->get($name[1], false)) || + (\is_null($result = $this->get($name[1], false)) || $result === static::$null); if (! $isDefault || $shouldSet) { @@ -2448,7 +2984,7 @@ class Compiler $compiledName = $this->compileValue($name); // handle shorthand syntaxes : size / line-height... - if (in_array($compiledName, ['font', 'grid-row', 'grid-column', 'border-radius'])) { + if (\in_array($compiledName, ['font', 'grid-row', 'grid-column', 'border-radius'])) { if ($value[0] === Type::T_VARIABLE) { // if the font value comes from variable, the content is already reduced // (i.e., formulas were already calculated), so we need the original unreduced value @@ -2468,7 +3004,7 @@ class Compiler break; } - if ($compiledName === 'font' and $value[0] === Type::T_LIST && $value[1]==',') { + if ($compiledName === 'font' && $value[0] === Type::T_LIST && $value[1] === ',') { // this is the case if more than one font is given: example: "font: 400 1em/1.3 arial,helvetica" // we need to handle the first list element $shorthandValue=&$value[2][0]; @@ -2480,11 +3016,11 @@ class Compiler if ($shorthandDividerNeedsUnit) { $divider = $shorthandValue[3]; - if (is_array($divider)) { + if (\is_array($divider)) { $divider = $this->reduce($divider, true); } - if (intval($divider->dimension) and !count($divider->units)) { + if ($divider instanceof Number && \intval($divider->getDimension()) && $divider->unitless()) { $revert = false; } } @@ -2497,17 +3033,18 @@ class Compiler if ($item[0] === Type::T_EXPRESSION && $item[1] === '/') { if ($maxShorthandDividers > 0) { $revert = true; + // if the list of values is too long, this has to be a shorthand, // otherwise it could be a real division - if (is_null($maxListElements) or count($shorthandValue[2]) <= $maxListElements) { + if (\is_null($maxListElements) || \count($shorthandValue[2]) <= $maxListElements) { if ($shorthandDividerNeedsUnit) { $divider = $item[3]; - if (is_array($divider)) { + if (\is_array($divider)) { $divider = $this->reduce($divider, true); } - if (intval($divider->dimension) and !count($divider->units)) { + if ($divider instanceof Number && \intval($divider->getDimension()) && $divider->unitless()) { $revert = false; } } @@ -2535,11 +3072,14 @@ class Compiler $compiledValue = $this->compileValue($value); - $line = $this->formatter->property( - $compiledName, - $compiledValue - ); - $this->appendOutputLine($out, Type::T_ASSIGN, $line); + // ignore empty value + if (\strlen($compiledValue)) { + $line = $this->formatter->property( + $compiledName, + $compiledValue + ); + $this->appendOutputLine($out, Type::T_ASSIGN, $line); + } break; case Type::T_COMMENT: @@ -2555,6 +3095,7 @@ class Compiler case Type::T_MIXIN: case Type::T_FUNCTION: list(, $block) = $child; + assert($block instanceof CallableBlock); // the block need to be able to go up to it's parent env to resolve vars $block->parentEnv = $this->getStoreEnv(); $this->set(static::$namespaces[$block->type] . $block->name, $block, true); @@ -2562,16 +3103,42 @@ class Compiler case Type::T_EXTEND: foreach ($child[1] as $sel) { + $replacedSel = $this->replaceSelfSelector($sel); + + if ($replacedSel !== $sel) { + throw $this->error('Parent selectors aren\'t allowed here.'); + } + $results = $this->evalSelectors([$sel]); foreach ($results as $result) { + if (\count($result) !== 1) { + throw $this->error('complex selectors may not be extended.'); + } + // only use the first one - $result = current($result); + $result = $result[0]; $selectors = $out->selectors; if (! $selectors && isset($child['selfParent'])) { $selectors = $this->multiplySelectors($this->env, $child['selfParent']); } + assert($selectors !== null); + + if (\count($result) > 1) { + $replacement = implode(', ', $result); + $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); + $line = $this->sourceLine; + + $message = <<logger->warn($message); + } $this->pushExtends($result, $selectors, $child); } @@ -2580,14 +3147,16 @@ class Compiler case Type::T_IF: list(, $if) = $child; + assert($if instanceof IfBlock); if ($this->isTruthy($this->reduce($if->cond, true))) { return $this->compileChildren($if->children, $out); } foreach ($if->cases as $case) { - if ($case->type === Type::T_ELSE || - $case->type === Type::T_ELSEIF && $this->isTruthy($this->reduce($case->cond)) + if ( + $case instanceof ElseBlock || + $case instanceof ElseifBlock && $this->isTruthy($this->reduce($case->cond)) ) { return $this->compileChildren($case->children, $out); } @@ -2596,13 +3165,14 @@ class Compiler case Type::T_EACH: list(, $each) = $child; + assert($each instanceof EachBlock); - $list = $this->coerceList($this->reduce($each->list)); + $list = $this->coerceList($this->reduce($each->list), ',', true); $this->pushEnv(); foreach ($list[2] as $item) { - if (count($each->vars) === 1) { + if (\count($each->vars) === 1) { $this->set($each->vars[0], $item, true); } else { list(,, $values) = $this->coerceList($item); @@ -2615,87 +3185,78 @@ class Compiler $ret = $this->compileChildren($each->children, $out); if ($ret) { - if ($ret[0] !== Type::T_CONTROL) { - $this->popEnv(); + $store = $this->env->store; + $this->popEnv(); + $this->backPropagateEnv($store, $each->vars); - return $ret; - } - - if ($ret[1]) { - break; - } + return $ret; } } - + $store = $this->env->store; $this->popEnv(); + $this->backPropagateEnv($store, $each->vars); + break; case Type::T_WHILE: list(, $while) = $child; + assert($while instanceof WhileBlock); while ($this->isTruthy($this->reduce($while->cond, true))) { $ret = $this->compileChildren($while->children, $out); if ($ret) { - if ($ret[0] !== Type::T_CONTROL) { - return $ret; - } - - if ($ret[1]) { - break; - } + return $ret; } } break; case Type::T_FOR: list(, $for) = $child; + assert($for instanceof ForBlock); - $start = $this->reduce($for->start, true); - $end = $this->reduce($for->end, true); + $startNumber = $this->assertNumber($this->reduce($for->start, true)); + $endNumber = $this->assertNumber($this->reduce($for->end, true)); - if (! ($start[2] == $end[2] || $end->unitless())) { - $this->throwError('Incompatible units: "%s" and "%s".', $start->unitStr(), $end->unitStr()); + $start = $this->assertInteger($startNumber); - break; - } + $numeratorUnits = $startNumber->getNumeratorUnits(); + $denominatorUnits = $startNumber->getDenominatorUnits(); - $unit = $start[2]; - $start = $start[1]; - $end = $end[1]; + $end = $this->assertInteger($endNumber->coerce($numeratorUnits, $denominatorUnits)); $d = $start < $end ? 1 : -1; + $this->pushEnv(); + for (;;) { - if ((! $for->until && $start - $d == $end) || + if ( + (! $for->until && $start - $d == $end) || ($for->until && $start == $end) ) { break; } - $this->set($for->var, new Node\Number($start, $unit)); + $this->set($for->var, new Number($start, $numeratorUnits, $denominatorUnits)); $start += $d; $ret = $this->compileChildren($for->children, $out); if ($ret) { - if ($ret[0] !== Type::T_CONTROL) { - return $ret; - } + $store = $this->env->store; + $this->popEnv(); + $this->backPropagateEnv($store, [$for->var]); - if ($ret[1]) { - break; - } + return $ret; } } + + $store = $this->env->store; + $this->popEnv(); + $this->backPropagateEnv($store, [$for->var]); + break; - case Type::T_BREAK: - return [Type::T_CONTROL, true]; - - case Type::T_CONTINUE: - return [Type::T_CONTROL, false]; - case Type::T_RETURN: return $this->reduce($child[1], true); @@ -2710,24 +3271,22 @@ class Compiler $mixin = $this->get(static::$namespaces['mixin'] . $name, false); if (! $mixin) { - $this->throwError("Undefined mixin $name"); - break; + throw $this->error("Undefined mixin $name"); } + assert($mixin instanceof CallableBlock); + $callingScope = $this->getStoreEnv(); // push scope, apply args $this->pushEnv(); $this->env->depth--; - $storeEnv = $this->storeEnv; - $this->storeEnv = $this->env; - // Find the parent selectors in the env to be able to know what '&' refers to in the mixin // and assign this fake parent to childs $selfParent = null; - if (isset($child['selfParent']) && isset($child['selfParent']->selectors)) { + if (isset($child['selfParent']) && $child['selfParent'] instanceof Block && isset($child['selfParent']->selectors)) { $selfParent = $child['selfParent']; } else { $parentSelectors = $this->multiplySelectors($this->env); @@ -2737,7 +3296,7 @@ class Compiler $parent->selectors = $parentSelectors; foreach ($mixin->children as $k => $child) { - if (isset($child[1]) && is_object($child[1]) && $child[1] instanceof Block) { + if (isset($child[1]) && $child[1] instanceof Block) { $mixin->children[$k][1]->parent = $parent; } } @@ -2771,12 +3330,10 @@ class Compiler if (! empty($mixin->parentEnv)) { $this->env->declarationScopeParent = $mixin->parentEnv; } else { - $this->throwError("@mixin $name() without parentEnv"); + throw $this->error("@mixin $name() without parentEnv"); } - $this->compileChildrenNoReturn($mixin->children, $out, $selfParent, $this->env->marker . " " . $name); - - $this->storeEnv = $storeEnv; + $this->compileChildrenNoReturn($mixin->children, $out, $selfParent, $this->env->marker . ' ' . $name); $this->popEnv(); break; @@ -2788,9 +3345,6 @@ class Compiler $argContent = $child[1]; if (! $content) { - $content = new \stdClass(); - $content->scope = new \stdClass(); - $content->children = $env->parent->block->children; break; } @@ -2799,7 +3353,7 @@ class Compiler if (isset($argUsing) && isset($argContent)) { // Get the arguments provided for the content with the names provided in the "using" argument list - $this->storeEnv = $this->env; + $this->storeEnv = null; $varsUsing = $this->applyArguments($argUsing, $argContent, false); } @@ -2819,54 +3373,58 @@ class Compiler case Type::T_DEBUG: list(, $value) = $child; - $fname = $this->sourceNames[$this->sourceIndex]; + $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); $line = $this->sourceLine; - $value = $this->compileValue($this->reduce($value, true)); + $value = $this->compileDebugValue($value); - fwrite($this->stderr, "File $fname on line $line DEBUG: $value\n"); + $this->logger->debug("$fname:$line DEBUG: $value"); break; case Type::T_WARN: list(, $value) = $child; - $fname = $this->sourceNames[$this->sourceIndex]; + $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); $line = $this->sourceLine; - $value = $this->compileValue($this->reduce($value, true)); + $value = $this->compileDebugValue($value); - fwrite($this->stderr, "File $fname on line $line WARN: $value\n"); + $this->logger->warn("$value\n on line $line of $fname"); break; case Type::T_ERROR: list(, $value) = $child; - $fname = $this->sourceNames[$this->sourceIndex]; + $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); $line = $this->sourceLine; $value = $this->compileValue($this->reduce($value, true)); - $this->throwError("File $fname on line $line ERROR: $value\n"); - break; - - case Type::T_CONTROL: - $this->throwError('@break/@continue not permitted in this scope'); - break; + throw $this->error("File $fname on line $line ERROR: $value\n"); default: - $this->throwError("unknown child type: $child[0]"); + throw $this->error("unknown child type: $child[0]"); } + + return null; } /** * Reduce expression to string * * @param array $exp + * @param bool $keepParens * * @return array */ - protected function expToString($exp) + protected function expToString($exp, $keepParens = false) { - list(, $op, $left, $right, /* $inParens */, $whiteLeft, $whiteRight) = $exp; + list(, $op, $left, $right, $inParens, $whiteLeft, $whiteRight) = $exp; - $content = [$this->reduce($left)]; + $content = []; + + if ($keepParens && $inParens) { + $content[] = '('; + } + + $content[] = $this->reduce($left); if ($whiteLeft) { $content[] = ' '; @@ -2880,17 +3438,21 @@ class Compiler $content[] = $this->reduce($right); + if ($keepParens && $inParens) { + $content[] = ')'; + } + return [Type::T_STRING, '', $content]; } /** * Is truthy? * - * @param array $value + * @param array|Number $value * - * @return boolean + * @return bool */ - protected function isTruthy($value) + public function isTruthy($value) { return $value !== static::$false && $value !== static::$null; } @@ -2900,7 +3462,7 @@ class Compiler * * @param string $value * - * @return boolean + * @return bool */ protected function isImmediateRelationshipCombinator($value) { @@ -2912,7 +3474,7 @@ class Compiler * * @param array $value * - * @return boolean + * @return bool */ protected function shouldEval($value) { @@ -2934,15 +3496,15 @@ class Compiler /** * Reduce value * - * @param array $value - * @param boolean $inExp + * @param array|Number $value + * @param bool $inExp * - * @return null|string|array|\ScssPhp\ScssPhp\Node\Number + * @return array|Number */ protected function reduce($value, $inExp = false) { - if (is_null($value)) { - return null; + if ($value instanceof Number) { + return $value; } switch ($value[0]) { @@ -2959,8 +3521,9 @@ class Compiler } // special case: looks like css shorthand - if ($opName == 'div' && ! $inParens && ! $inExp && isset($right[2]) && - (($right[0] !== Type::T_NUMBER && $right[2] != '') || + if ( + $opName == 'div' && ! $inParens && ! $inExp && + (($right[0] !== Type::T_NUMBER && isset($right[2]) && $right[2] != '') || ($right[0] === Type::T_NUMBER && ! $right->unitless())) ) { return $this->expToString($value); @@ -2975,73 +3538,24 @@ class Compiler $ucLType = ucfirst($ltype); $ucRType = ucfirst($rtype); + $shouldEval = $inParens || $inExp; + // this tries: // 1. op[op name][left type][right type] - // 2. op[left type][right type] (passing the op as first arg + // 2. op[left type][right type] (passing the op as first arg) // 3. op[op name] - $fn = "op${ucOpName}${ucLType}${ucRType}"; + if (\is_callable([$this, $fn = "op${ucOpName}${ucLType}${ucRType}"])) { + $out = $this->$fn($left, $right, $shouldEval); + } elseif (\is_callable([$this, $fn = "op${ucLType}${ucRType}"])) { + $out = $this->$fn($op, $left, $right, $shouldEval); + } elseif (\is_callable([$this, $fn = "op${ucOpName}"])) { + $out = $this->$fn($left, $right, $shouldEval); + } else { + $out = null; + } - if (is_callable([$this, $fn]) || - (($fn = "op${ucLType}${ucRType}") && - is_callable([$this, $fn]) && - $passOp = true) || - (($fn = "op${ucOpName}") && - is_callable([$this, $fn]) && - $genOp = true) - ) { - $coerceUnit = false; - - if (! isset($genOp) && - $left[0] === Type::T_NUMBER && $right[0] === Type::T_NUMBER - ) { - $coerceUnit = true; - - switch ($opName) { - case 'mul': - $targetUnit = $left[2]; - - foreach ($right[2] as $unit => $exp) { - $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) + $exp; - } - break; - - case 'div': - $targetUnit = $left[2]; - - foreach ($right[2] as $unit => $exp) { - $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) - $exp; - } - break; - - case 'mod': - $targetUnit = $left[2]; - break; - - default: - $targetUnit = $left->unitless() ? $right[2] : $left[2]; - } - - if (! $left->unitless() && ! $right->unitless()) { - $left = $left->normalize(); - $right = $right->normalize(); - } - } - - $shouldEval = $inParens || $inExp; - - if (isset($passOp)) { - $out = $this->$fn($op, $left, $right, $shouldEval); - } else { - $out = $this->$fn($left, $right, $shouldEval); - } - - if (isset($out)) { - if ($coerceUnit && $out[0] === Type::T_NUMBER) { - $out = $out->coerce($targetUnit); - } - - return $out; - } + if (isset($out)) { + return $out; } return $this->expToString($value); @@ -3052,13 +3566,13 @@ class Compiler $inExp = $inExp || $this->shouldEval($exp); $exp = $this->reduce($exp); - if ($exp[0] === Type::T_NUMBER) { + if ($exp instanceof Number) { switch ($op) { case '+': - return new Node\Number($exp[1], $exp[2]); + return $exp; case '-': - return new Node\Number(-$exp[1], $exp[2]); + return $exp->unaryMinus(); } } @@ -3083,6 +3597,14 @@ class Compiler foreach ($value[2] as &$item) { $item = $this->reduce($item); } + unset($item); + + if (isset($value[3]) && \is_array($value[3])) { + foreach ($value[3] as &$item) { + $item = $this->reduce($item); + } + unset($item); + } return $value; @@ -3099,7 +3621,7 @@ class Compiler case Type::T_STRING: foreach ($value[2] as &$item) { - if (is_array($item) || $item instanceof \ArrayAccess) { + if (\is_array($item) || $item instanceof Number) { $item = $this->reduce($item); } } @@ -3110,7 +3632,7 @@ class Compiler $value[1] = $this->reduce($value[1]); if ($inExp) { - return $value[1]; + return [Type::T_KEYWORD, $this->compileValue($value, false)]; } return $value; @@ -3119,8 +3641,9 @@ class Compiler return $this->fncall($value[1], $value[2]); case Type::T_SELF: - $selfSelector = $this->multiplySelectors($this->env); - $selfSelector = $this->collapseSelectors($selfSelector, true); + $selfParent = ! empty($this->env->block->selfParent) ? $this->env->block->selfParent : null; + $selfSelector = $this->multiplySelectors($this->env, $selfParent); + $selfSelector = $this->collapseSelectorsAsList($selfSelector); return $selfSelector; @@ -3132,35 +3655,301 @@ class Compiler /** * Function caller * - * @param string $name - * @param array $argValues + * @param string|array $functionReference + * @param array $argValues * - * @return array|null + * @return array|Number */ - protected function fncall($name, $argValues) + protected function fncall($functionReference, $argValues) { - // SCSS @function - if ($this->callScssFunction($name, $argValues, $returnValue)) { - return $returnValue; - } + // a string means this is a static hard reference coming from the parsing + if (is_string($functionReference)) { + $name = $functionReference; - // native PHP functions - if ($this->callNativeFunction($name, $argValues, $returnValue)) { - return $returnValue; - } - - // for CSS functions, simply flatten the arguments into a list - $listArgs = []; - - foreach ((array) $argValues as $arg) { - if (empty($arg[0])) { - $listArgs[] = $this->reduce($arg[1]); + $functionReference = $this->getFunctionReference($name); + if ($functionReference === static::$null || $functionReference[0] !== Type::T_FUNCTION_REFERENCE) { + $functionReference = [Type::T_FUNCTION, $name, [Type::T_LIST, ',', []]]; } } - return [Type::T_FUNCTION, $name, [Type::T_LIST, ',', $listArgs]]; + // a function type means we just want a plain css function call + if ($functionReference[0] === Type::T_FUNCTION) { + // for CSS functions, simply flatten the arguments into a list + $listArgs = []; + + foreach ((array) $argValues as $arg) { + if (empty($arg[0]) || count($argValues) === 1) { + $listArgs[] = $this->reduce($this->stringifyFncallArgs($arg[1])); + } + } + + return [Type::T_FUNCTION, $functionReference[1], [Type::T_LIST, ',', $listArgs]]; + } + + if ($functionReference === static::$null || $functionReference[0] !== Type::T_FUNCTION_REFERENCE) { + return static::$defaultValue; + } + + + switch ($functionReference[1]) { + // SCSS @function + case 'scss': + return $this->callScssFunction($functionReference[3], $argValues); + + // native PHP functions + case 'user': + case 'native': + list(,,$name, $fn, $prototype) = $functionReference; + + // special cases of css valid functions min/max + $name = strtolower($name); + if (\in_array($name, ['min', 'max']) && count($argValues) >= 1) { + $cssFunction = $this->cssValidArg( + [Type::T_FUNCTION_CALL, $name, $argValues], + ['min', 'max', 'calc', 'env', 'var'] + ); + if ($cssFunction !== false) { + return $cssFunction; + } + } + $returnValue = $this->callNativeFunction($name, $fn, $prototype, $argValues); + + if (! isset($returnValue)) { + return $this->fncall([Type::T_FUNCTION, $name, [Type::T_LIST, ',', []]], $argValues); + } + + return $returnValue; + + default: + return static::$defaultValue; + } } + /** + * @param array|Number $arg + * @param string[] $allowed_function + * @param bool $inFunction + * + * @return array|Number|false + */ + protected function cssValidArg($arg, $allowed_function = [], $inFunction = false) + { + if ($arg instanceof Number) { + return $this->stringifyFncallArgs($arg); + } + + switch ($arg[0]) { + case Type::T_INTERPOLATE: + return [Type::T_KEYWORD, $this->CompileValue($arg)]; + + case Type::T_FUNCTION: + if (! \in_array($arg[1], $allowed_function)) { + return false; + } + if ($arg[2][0] === Type::T_LIST) { + foreach ($arg[2][2] as $k => $subarg) { + $arg[2][2][$k] = $this->cssValidArg($subarg, $allowed_function, $arg[1]); + if ($arg[2][2][$k] === false) { + return false; + } + } + } + return $arg; + + case Type::T_FUNCTION_CALL: + if (! \in_array($arg[1], $allowed_function)) { + return false; + } + $cssArgs = []; + foreach ($arg[2] as $argValue) { + if ($argValue === static::$null) { + return false; + } + $cssArg = $this->cssValidArg($argValue[1], $allowed_function, $arg[1]); + if (empty($argValue[0]) && $cssArg !== false) { + $cssArgs[] = [$argValue[0], $cssArg]; + } else { + return false; + } + } + + return $this->fncall([Type::T_FUNCTION, $arg[1], [Type::T_LIST, ',', []]], $cssArgs); + + case Type::T_STRING: + case Type::T_KEYWORD: + if (!$inFunction or !\in_array($inFunction, ['calc', 'env', 'var'])) { + return false; + } + return $this->stringifyFncallArgs($arg); + + case Type::T_LIST: + if (!$inFunction) { + return false; + } + if (empty($arg['enclosing']) and $arg[1] === '') { + foreach ($arg[2] as $k => $subarg) { + $arg[2][$k] = $this->cssValidArg($subarg, $allowed_function, $inFunction); + if ($arg[2][$k] === false) { + return false; + } + } + $arg[0] = Type::T_STRING; + return $arg; + } + return false; + + case Type::T_EXPRESSION: + if (! \in_array($arg[1], ['+', '-', '/', '*'])) { + return false; + } + $arg[2] = $this->cssValidArg($arg[2], $allowed_function, $inFunction); + $arg[3] = $this->cssValidArg($arg[3], $allowed_function, $inFunction); + if ($arg[2] === false || $arg[3] === false) { + return false; + } + return $this->expToString($arg, true); + + case Type::T_VARIABLE: + case Type::T_SELF: + default: + return false; + } + } + + + /** + * Reformat fncall arguments to proper css function output + * + * @param array|Number $arg + * + * @return array|Number + */ + protected function stringifyFncallArgs($arg) + { + if ($arg instanceof Number) { + return $arg; + } + + switch ($arg[0]) { + case Type::T_LIST: + foreach ($arg[2] as $k => $v) { + $arg[2][$k] = $this->stringifyFncallArgs($v); + } + break; + + case Type::T_EXPRESSION: + if ($arg[1] === '/') { + $arg[2] = $this->stringifyFncallArgs($arg[2]); + $arg[3] = $this->stringifyFncallArgs($arg[3]); + $arg[5] = $arg[6] = false; // no space around / + $arg = $this->expToString($arg); + } + break; + + case Type::T_FUNCTION_CALL: + $name = strtolower($arg[1]); + + if (in_array($name, ['max', 'min', 'calc'])) { + $args = $arg[2]; + $arg = $this->fncall([Type::T_FUNCTION, $name, [Type::T_LIST, ',', []]], $args); + } + break; + } + + return $arg; + } + + /** + * Find a function reference + * @param string $name + * @param bool $safeCopy + * @return array + */ + protected function getFunctionReference($name, $safeCopy = false) + { + // SCSS @function + if ($func = $this->get(static::$namespaces['function'] . $name, false)) { + if ($safeCopy) { + $func = clone $func; + } + + return [Type::T_FUNCTION_REFERENCE, 'scss', $name, $func]; + } + + // native PHP functions + + // try to find a native lib function + $normalizedName = $this->normalizeName($name); + + if (isset($this->userFunctions[$normalizedName])) { + // see if we can find a user function + list($f, $prototype) = $this->userFunctions[$normalizedName]; + + return [Type::T_FUNCTION_REFERENCE, 'user', $name, $f, $prototype]; + } + + $lowercasedName = strtolower($normalizedName); + + // Special functions overriding a CSS function are case-insensitive. We normalize them as lowercase + // to avoid the deprecation warning about the wrong case being used. + if ($lowercasedName === 'min' || $lowercasedName === 'max') { + $normalizedName = $lowercasedName; + } + + if (($f = $this->getBuiltinFunction($normalizedName)) && \is_callable($f)) { + /** @var string $libName */ + $libName = $f[1]; + $prototype = isset(static::$$libName) ? static::$$libName : null; + + // All core functions have a prototype defined. Not finding the + // prototype can mean 2 things: + // - the function comes from a child class (deprecated just after) + // - the function was found with a different case, which relates to calling the + // wrong Sass function due to our camelCase usage (`fade-in()` vs `fadein()`), + // because PHP method names are case-insensitive while property names are + // case-sensitive. + if ($prototype === null || strtolower($normalizedName) !== $normalizedName) { + $r = new \ReflectionMethod($this, $libName); + $actualLibName = $r->name; + + if ($actualLibName !== $libName || strtolower($normalizedName) !== $normalizedName) { + $kebabCaseName = preg_replace('~(?<=\\w)([A-Z])~', '-$1', substr($actualLibName, 3)); + assert($kebabCaseName !== null); + $originalName = strtolower($kebabCaseName); + $warning = "Calling built-in functions with a non-standard name is deprecated since Scssphp 1.8.0 and will not work anymore in 2.0 (they will be treated as CSS function calls instead).\nUse \"$originalName\" instead of \"$name\"."; + @trigger_error($warning, E_USER_DEPRECATED); + $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); + $line = $this->sourceLine; + Warn::deprecation("$warning\n on line $line of $fname"); + + // Use the actual function definition + $prototype = isset(static::$$actualLibName) ? static::$$actualLibName : null; + $f[1] = $libName = $actualLibName; + } + } + + if (\get_class($this) !== __CLASS__ && !isset($this->warnedChildFunctions[$libName])) { + $r = new \ReflectionMethod($this, $libName); + $declaringClass = $r->getDeclaringClass()->name; + + $needsWarning = $this->warnedChildFunctions[$libName] = $declaringClass !== __CLASS__; + + if ($needsWarning) { + if (method_exists(__CLASS__, $libName)) { + @trigger_error(sprintf('Overriding the "%s" core function by extending the Compiler is deprecated and will be unsupported in 2.0. Remove the "%s::%s" method.', $normalizedName, $declaringClass, $libName), E_USER_DEPRECATED); + } else { + @trigger_error(sprintf('Registering custom functions by extending the Compiler and using the lib* discovery mechanism is deprecated and will be removed in 2.0. Replace the "%s::%s" method with registering the "%s" function through "Compiler::registerFunction".', $declaringClass, $libName, $normalizedName), E_USER_DEPRECATED); + } + } + } + + return [Type::T_FUNCTION_REFERENCE, 'native', $name, $f, $prototype]; + } + + return static::$null; + } + + /** * Normalize name * @@ -3176,14 +3965,20 @@ class Compiler /** * Normalize value * - * @param array $value + * @internal * - * @return array + * @param array|Number $value + * + * @return array|Number */ public function normalizeValue($value) { $value = $this->coerceForExpression($this->reduce($value)); + if ($value instanceof Number) { + return $value; + } + switch ($value[0]) { case Type::T_LIST: $value = $this->extractInterpolation($value); @@ -3200,14 +3995,15 @@ class Compiler unset($value['enclosing']); } + if ($value[1] === '' && count($value[2]) > 1) { + $value[1] = ' '; + } + return $value; case Type::T_STRING: return [$value[0], '"', [$this->compileStringContent($value)]]; - case Type::T_NUMBER: - return $value->normalize(); - case Type::T_INTERPOLATE: return [Type::T_KEYWORD, $this->compileValue($value)]; @@ -3219,70 +4015,66 @@ class Compiler /** * Add numbers * - * @param array $left - * @param array $right + * @param Number $left + * @param Number $right * - * @return \ScssPhp\ScssPhp\Node\Number + * @return Number */ - protected function opAddNumberNumber($left, $right) + protected function opAddNumberNumber(Number $left, Number $right) { - return new Node\Number($left[1] + $right[1], $left[2]); + return $left->plus($right); } /** * Multiply numbers * - * @param array $left - * @param array $right + * @param Number $left + * @param Number $right * - * @return \ScssPhp\ScssPhp\Node\Number + * @return Number */ - protected function opMulNumberNumber($left, $right) + protected function opMulNumberNumber(Number $left, Number $right) { - return new Node\Number($left[1] * $right[1], $left[2]); + return $left->times($right); } /** * Subtract numbers * - * @param array $left - * @param array $right + * @param Number $left + * @param Number $right * - * @return \ScssPhp\ScssPhp\Node\Number + * @return Number */ - protected function opSubNumberNumber($left, $right) + protected function opSubNumberNumber(Number $left, Number $right) { - return new Node\Number($left[1] - $right[1], $left[2]); + return $left->minus($right); } /** * Divide numbers * - * @param array $left - * @param array $right + * @param Number $left + * @param Number $right * - * @return array|\ScssPhp\ScssPhp\Node\Number + * @return Number */ - protected function opDivNumberNumber($left, $right) + protected function opDivNumberNumber(Number $left, Number $right) { - if ($right[1] == 0) { - return [Type::T_STRING, '', [$left[1] . $left[2] . '/' . $right[1] . $right[2]]]; - } - - return new Node\Number($left[1] / $right[1], $left[2]); + return $left->dividedBy($right); } /** * Mod numbers * - * @param array $left - * @param array $right + * @param Number $left + * @param Number $right * - * @return \ScssPhp\ScssPhp\Node\Number + * @return Number */ - protected function opModNumberNumber($left, $right) + protected function opModNumberNumber(Number $left, Number $right) { - return new Node\Number($left[1] % $right[1], $left[2]); + return $left->modulo($right); } /** @@ -3321,11 +4113,11 @@ class Compiler /** * Boolean and * - * @param array $left - * @param array $right - * @param boolean $shouldEval + * @param array|Number $left + * @param array|Number $right + * @param bool $shouldEval * - * @return array|null + * @return array|Number|null */ protected function opAnd($left, $right, $shouldEval) { @@ -3349,11 +4141,11 @@ class Compiler /** * Boolean or * - * @param array $left - * @param array $right - * @param boolean $shouldEval + * @param array|Number $left + * @param array|Number $right + * @param bool $shouldEval * - * @return array|null + * @return array|Number|null */ protected function opOr($left, $right, $shouldEval) { @@ -3385,6 +4177,15 @@ class Compiler */ protected function opColorColor($op, $left, $right) { + if ($op !== '==' && $op !== '!=') { + $warning = "Color arithmetic is deprecated and will be an error in future versions.\n" + . "Consider using Sass's color functions instead."; + $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); + $line = $this->sourceLine; + + Warn::deprecation("$warning\n on line $line of $fname"); + } + $out = [Type::T_COLOR]; foreach ([1, 2, 3] as $i) { @@ -3405,13 +4206,16 @@ class Compiler break; case '%': + if ($rval == 0) { + throw $this->error("color: Can't take modulo by zero"); + } + $out[] = $lval % $rval; break; case '/': if ($rval == 0) { - $this->throwError("color: Can't divide by zero"); - break 2; + throw $this->error("color: Can't divide by zero"); } $out[] = (int) ($lval / $rval); @@ -3424,8 +4228,7 @@ class Compiler return $this->opNeq($left, $right); default: - $this->throwError("color: unknown op $op"); - break 2; + throw $this->error("color: unknown op $op"); } } @@ -3443,13 +4246,21 @@ class Compiler * * @param string $op * @param array $left - * @param array $right + * @param Number $right * * @return array */ - protected function opColorNumber($op, $left, $right) + protected function opColorNumber($op, $left, Number $right) { - $value = $right[1]; + if ($op === '==') { + return static::$false; + } + + if ($op === '!=') { + return static::$true; + } + + $value = $right->getDimension(); return $this->opColorColor( $op, @@ -3462,14 +4273,22 @@ class Compiler * Compare number and color * * @param string $op - * @param array $left + * @param Number $left * @param array $right * * @return array */ - protected function opNumberColor($op, $left, $right) + protected function opNumberColor($op, Number $left, $right) { - $value = $left[1]; + if ($op === '==') { + return static::$false; + } + + if ($op === '!=') { + return static::$true; + } + + $value = $left->getDimension(); return $this->opColorColor( $op, @@ -3481,8 +4300,8 @@ class Compiler /** * Compare number1 == number2 * - * @param array $left - * @param array $right + * @param array|Number $left + * @param array|Number $right * * @return array */ @@ -3502,8 +4321,8 @@ class Compiler /** * Compare number1 != number2 * - * @param array $left - * @param array $right + * @param array|Number $left + * @param array|Number $right * * @return array */ @@ -3521,70 +4340,81 @@ class Compiler } /** - * Compare number1 >= number2 + * Compare number1 == number2 * - * @param array $left - * @param array $right + * @param Number $left + * @param Number $right * * @return array */ - protected function opGteNumberNumber($left, $right) + protected function opEqNumberNumber(Number $left, Number $right) { - return $this->toBool($left[1] >= $right[1]); + return $this->toBool($left->equals($right)); + } + + /** + * Compare number1 != number2 + * + * @param Number $left + * @param Number $right + * + * @return array + */ + protected function opNeqNumberNumber(Number $left, Number $right) + { + return $this->toBool(!$left->equals($right)); + } + + /** + * Compare number1 >= number2 + * + * @param Number $left + * @param Number $right + * + * @return array + */ + protected function opGteNumberNumber(Number $left, Number $right) + { + return $this->toBool($left->greaterThanOrEqual($right)); } /** * Compare number1 > number2 * - * @param array $left - * @param array $right + * @param Number $left + * @param Number $right * * @return array */ - protected function opGtNumberNumber($left, $right) + protected function opGtNumberNumber(Number $left, Number $right) { - return $this->toBool($left[1] > $right[1]); + return $this->toBool($left->greaterThan($right)); } /** * Compare number1 <= number2 * - * @param array $left - * @param array $right + * @param Number $left + * @param Number $right * * @return array */ - protected function opLteNumberNumber($left, $right) + protected function opLteNumberNumber(Number $left, Number $right) { - return $this->toBool($left[1] <= $right[1]); + return $this->toBool($left->lessThanOrEqual($right)); } /** * Compare number1 < number2 * - * @param array $left - * @param array $right + * @param Number $left + * @param Number $right * * @return array */ - protected function opLtNumberNumber($left, $right) + protected function opLtNumberNumber(Number $left, Number $right) { - return $this->toBool($left[1] < $right[1]); - } - - /** - * Three-way comparison, aka spaceship operator - * - * @param array $left - * @param array $right - * - * @return \ScssPhp\ScssPhp\Node\Number - */ - protected function opCmpNumberNumber($left, $right) - { - $n = $left[1] - $right[1]; - - return new Node\Number($n ? $n / abs($n) : 0, ''); + return $this->toBool($left->lessThan($right)); } /** @@ -3592,7 +4422,7 @@ class Compiler * * @api * - * @param mixed $thing + * @param bool $thing * * @return array */ @@ -3601,6 +4431,53 @@ class Compiler return $thing ? static::$true : static::$false; } + /** + * Escape non printable chars in strings output as in dart-sass + * + * @internal + * + * @param string $string + * @param bool $inKeyword + * + * @return string + */ + public function escapeNonPrintableChars($string, $inKeyword = false) + { + static $replacement = []; + if (empty($replacement[$inKeyword])) { + for ($i = 0; $i < 32; $i++) { + if ($i !== 9 || $inKeyword) { + $replacement[$inKeyword][chr($i)] = '\\' . dechex($i) . ($inKeyword ? ' ' : chr(0)); + } + } + } + $string = str_replace(array_keys($replacement[$inKeyword]), array_values($replacement[$inKeyword]), $string); + // chr(0) is not a possible char from the input, so any chr(0) comes from our escaping replacement + if (strpos($string, chr(0)) !== false) { + if (substr($string, -1) === chr(0)) { + $string = substr($string, 0, -1); + } + $string = str_replace( + [chr(0) . '\\',chr(0) . ' '], + [ '\\', ' '], + $string + ); + if (strpos($string, chr(0)) !== false) { + $parts = explode(chr(0), $string); + $string = array_shift($parts); + while (count($parts)) { + $next = array_shift($parts); + if (strpos("0123456789abcdefABCDEF" . chr(9), $next[0]) !== false) { + $string .= " "; + } + $string .= $next; + } + } + } + + return $string; + } + /** * Compiles a primitive value into a CSS property value. * @@ -3614,17 +4491,22 @@ class Compiler * * @api * - * @param array $value + * @param array|Number $value + * @param bool $quote * - * @return string|array + * @return string */ - public function compileValue($value) + public function compileValue($value, $quote = true) { $value = $this->reduce($value); + if ($value instanceof Number) { + return $value->output($this); + } + switch ($value[0]) { case Type::T_KEYWORD: - return $value[1]; + return $this->escapeNonPrintableChars($value[1], true); case Type::T_COLOR: // [1] - red component (either number for a %) @@ -3637,18 +4519,18 @@ class Compiler $g = $this->compileRGBAValue($g); $b = $this->compileRGBAValue($b); - if (count($value) === 5) { + if (\count($value) === 5) { $alpha = $this->compileRGBAValue($value[4], true); if (! is_numeric($alpha) || $alpha < 1) { $colorName = Colors::RGBaToColorName($r, $g, $b, $alpha); - if (! is_null($colorName)) { + if (! \is_null($colorName)) { return $colorName; } if (is_numeric($alpha)) { - $a = new Node\Number($alpha, ''); + $a = new Number($alpha, ''); } else { $a = $alpha; } @@ -3663,7 +4545,7 @@ class Compiler $colorName = Colors::RGBaToColorName($r, $g, $b); - if (! is_null($colorName)) { + if (! \is_null($colorName)) { return $colorName; } @@ -3676,72 +4558,119 @@ class Compiler return $h; - case Type::T_NUMBER: - return $value->output($this); - case Type::T_STRING: - return $value[1] . $this->compileStringContent($value) . $value[1]; + $content = $this->compileStringContent($value, $quote); + + if ($value[1] && $quote) { + $content = str_replace('\\', '\\\\', $content); + + $content = $this->escapeNonPrintableChars($content); + + // force double quote as string quote for the output in certain cases + if ( + $value[1] === "'" && + (strpos($content, '"') === false or strpos($content, "'") !== false) + ) { + $value[1] = '"'; + } elseif ( + $value[1] === '"' && + (strpos($content, '"') !== false and strpos($content, "'") === false) + ) { + $value[1] = "'"; + } + + $content = str_replace($value[1], '\\' . $value[1], $content); + } + + return $value[1] . $content . $value[1]; case Type::T_FUNCTION: - $args = ! empty($value[2]) ? $this->compileValue($value[2]) : ''; + $args = ! empty($value[2]) ? $this->compileValue($value[2], $quote) : ''; return "$value[1]($args)"; + case Type::T_FUNCTION_REFERENCE: + $name = ! empty($value[2]) ? $value[2] : ''; + + return "get-function(\"$name\")"; + case Type::T_LIST: $value = $this->extractInterpolation($value); if ($value[0] !== Type::T_LIST) { - return $this->compileValue($value); + return $this->compileValue($value, $quote); } list(, $delim, $items) = $value; - $pre = $post = ""; + $pre = $post = ''; + if (! empty($value['enclosing'])) { switch ($value['enclosing']) { case 'parent': - //$pre = "("; - //$post = ")"; + //$pre = '('; + //$post = ')'; break; case 'forced_parent': - $pre = "("; - $post = ")"; + $pre = '('; + $post = ')'; break; case 'bracket': case 'forced_bracket': - $pre = "["; - $post = "]"; + $pre = '['; + $post = ']'; break; } } + $separator = $delim === '/' ? ' /' : $delim; + $prefix_value = ''; + if ($delim !== ' ') { $prefix_value = ' '; } $filtered = []; + $same_string_quote = null; foreach ($items as $item) { + if (\is_null($same_string_quote)) { + $same_string_quote = false; + if ($item[0] === Type::T_STRING) { + $same_string_quote = $item[1]; + foreach ($items as $ii) { + if ($ii[0] !== Type::T_STRING) { + $same_string_quote = false; + break; + } + } + } + } if ($item[0] === Type::T_NULL) { continue; } + if ($same_string_quote === '"' && $item[0] === Type::T_STRING && $item[1]) { + $item[1] = $same_string_quote; + } - $compiled = $this->compileValue($item); - if ($prefix_value && strlen($compiled)) { + $compiled = $this->compileValue($item, $quote); + + if ($prefix_value && \strlen($compiled)) { $compiled = $prefix_value . $compiled; } + $filtered[] = $compiled; } - return $pre . substr(implode("$delim", $filtered), strlen($prefix_value)) . $post; + return $pre . substr(implode($separator, $filtered), \strlen($prefix_value)) . $post; case Type::T_MAP: $keys = $value[1]; $values = $value[2]; $filtered = []; - for ($i = 0, $s = count($keys); $i < $s; $i++) { - $filtered[$this->compileValue($keys[$i])] = $this->compileValue($values[$i]); + for ($i = 0, $s = \count($keys); $i < $s; $i++) { + $filtered[$this->compileValue($keys[$i], $quote)] = $this->compileValue($values[$i], $quote); } array_walk($filtered, function (&$value, $key) { @@ -3761,8 +4690,9 @@ class Compiler $delim .= ' '; } - $left = count($left[2]) > 0 ? - $this->compileValue($left) . $delim . $whiteLeft: ''; + $left = \count($left[2]) > 0 + ? $this->compileValue($left, $quote) . $delim . $whiteLeft + : ''; $delim = $right[1]; @@ -3770,15 +4700,19 @@ class Compiler $delim .= ' '; } - $right = count($right[2]) > 0 ? - $whiteRight . $delim . $this->compileValue($right) : ''; + $right = \count($right[2]) > 0 ? + $whiteRight . $delim . $this->compileValue($right, $quote) : ''; - return $left . $this->compileValue($interpolate) . $right; + return $left . $this->compileValue($interpolate, $quote) . $right; case Type::T_INTERPOLATE: // strip quotes if it's a string $reduced = $this->reduce($value[1]); + if ($reduced instanceof Number) { + return $this->compileValue($reduced, $quote); + } + switch ($reduced[0]) { case Type::T_LIST: $reduced = $this->extractInterpolation($reduced); @@ -3800,14 +4734,12 @@ class Compiler continue; } - $temp = $this->compileValue([Type::T_KEYWORD, $item]); - - if ($temp[0] === Type::T_STRING) { - $filtered[] = $this->compileStringContent($temp); - } elseif ($temp[0] === Type::T_KEYWORD) { - $filtered[] = $temp[1]; + if ($item[0] === Type::T_STRING) { + $filtered[] = $this->compileStringContent($item, $quote); + } elseif ($item[0] === Type::T_KEYWORD) { + $filtered[] = $item[1]; } else { - $filtered[] = $this->compileValue($temp); + $filtered[] = $this->compileValue($item, $quote); } } @@ -3815,14 +4747,14 @@ class Compiler break; case Type::T_STRING: - $reduced = [Type::T_KEYWORD, $this->compileStringContent($reduced)]; + $reduced = [Type::T_STRING, '', [$this->compileStringContent($reduced)]]; break; case Type::T_NULL: $reduced = [Type::T_KEYWORD, '']; } - return $this->compileValue($reduced); + return $this->compileValue($reduced, $quote); case Type::T_NULL: return 'null'; @@ -3831,7 +4763,29 @@ class Compiler return $this->compileCommentValue($value); default: - $this->throwError("unknown value type: ".json_encode($value)); + throw $this->error('unknown value type: ' . json_encode($value)); + } + } + + /** + * @param array|Number $value + * + * @return string + */ + protected function compileDebugValue($value) + { + $value = $this->reduce($value, true); + + if ($value instanceof Number) { + return $this->compileValue($value); + } + + switch ($value[0]) { + case Type::T_STRING: + return $this->compileStringContent($value); + + default: + return $this->compileValue($value); } } @@ -3841,26 +4795,50 @@ class Compiler * @param array $list * * @return string + * + * @deprecated */ protected function flattenList($list) { + @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); + return $this->compileValue($list); } + /** + * Gets the text of a Sass string + * + * Calling this method on anything else than a SassString is unsupported. Use {@see assertString} first + * to ensure that the value is indeed a string. + * + * @param array $value + * + * @return string + */ + public function getStringText(array $value) + { + if ($value[0] !== Type::T_STRING) { + throw new \InvalidArgumentException('The argument is not a sass string. Did you forgot to use "assertString"?'); + } + + return $this->compileStringContent($value); + } + /** * Compile string content * * @param array $string + * @param bool $quote * * @return string */ - protected function compileStringContent($string) + protected function compileStringContent($string, $quote = true) { $parts = []; foreach ($string[2] as $part) { - if (is_array($part) || $part instanceof \ArrayAccess) { - $parts[] = $this->compileValue($part); + if (\is_array($part) || $part instanceof Number) { + $parts[] = $this->compileValue($part, $quote); } else { $parts[] = $part; } @@ -3882,8 +4860,8 @@ class Compiler foreach ($items as $i => $item) { if ($item[0] === Type::T_INTERPOLATE) { - $before = [Type::T_LIST, $list[1], array_slice($items, 0, $i)]; - $after = [Type::T_LIST, $list[1], array_slice($items, $i + 1)]; + $before = [Type::T_LIST, $list[1], \array_slice($items, 0, $i)]; + $after = [Type::T_LIST, $list[1], \array_slice($items, $i + 1)]; return [Type::T_INTERPOLATED, $item, $before, $after]; } @@ -3908,7 +4886,7 @@ class Compiler $selfParentSelectors = null; - if (! is_null($selfParent) && $selfParent->selectors) { + if (! \is_null($selfParent) && $selfParent->selectors) { $selfParentSelectors = $this->evalSelectors($selfParent->selectors); } @@ -3924,8 +4902,8 @@ class Compiler $prevSelectors = $selectors; $selectors = []; - foreach ($prevSelectors as $selector) { - foreach ($parentSelectors as $parent) { + foreach ($parentSelectors as $parent) { + foreach ($prevSelectors as $selector) { if ($selfParentSelectors) { foreach ($selfParentSelectors as $selfParent) { // if no '&' in the selector, each call will give same result, only add once @@ -3945,16 +4923,21 @@ class Compiler $selectors = array_values($selectors); + // case we are just starting a at-root : nothing to multiply but parentSelectors + if (! $selectors && $selfParentSelectors) { + $selectors = $selfParentSelectors; + } + return $selectors; } /** * Join selectors; looks for & to replace, or append parent before child * - * @param array $parent - * @param array $child - * @param boolean &$stillHasSelf - * @param array $selfParentSelectors + * @param array $parent + * @param array $child + * @param bool $stillHasSelf + * @param array $selfParentSelectors * @return array */ @@ -3975,7 +4958,7 @@ class Compiler if ($p === static::$selfSelector && ! $setSelf) { $setSelf = true; - if (is_null($selfParentSelectors)) { + if (\is_null($selfParentSelectors)) { $selfParentSelectors = $parent; } @@ -3986,7 +4969,7 @@ class Compiler } foreach ($parentPart as $pp) { - if (is_array($pp)) { + if (\is_array($pp)) { $flatten = []; array_walk_recursive($pp, function ($a) use (&$flatten) { @@ -4020,7 +5003,8 @@ class Compiler */ protected function multiplyMedia(Environment $env = null, $childQueries = null) { - if (! isset($env) || + if ( + ! isset($env) || ! empty($env->block->type) && $env->block->type !== Type::T_MEDIA ) { return $childQueries; @@ -4031,6 +5015,8 @@ class Compiler return $this->multiplyMedia($env->parent, $childQueries); } + assert($env->block instanceof MediaBlock); + $parentQueries = isset($env->block->queryList) ? $env->block->queryList : [[[Type::T_MEDIA_VALUE, $env->block->value]]]; @@ -4043,7 +5029,7 @@ class Compiler list($this->env, $this->storeEnv) = $store; - if (is_null($childQueries)) { + if (\is_null($childQueries)) { $childQueries = $parentQueries; } else { $originalQueries = $childQueries; @@ -4066,9 +5052,11 @@ class Compiler /** * Convert env linked list to stack * - * @param \ScssPhp\ScssPhp\Compiler\Environment $env + * @param Environment $env * - * @return array + * @return Environment[] + * + * @phpstan-return non-empty-array */ protected function compactEnv(Environment $env) { @@ -4082,9 +5070,11 @@ class Compiler /** * Convert env stack to singly linked list * - * @param array $envs + * @param Environment[] $envs * - * @return \ScssPhp\ScssPhp\Compiler\Environment + * @return Environment + * + * @phpstan-param non-empty-array $envs */ protected function extractEnv($envs) { @@ -4105,25 +5095,47 @@ class Compiler */ protected function pushEnv(Block $block = null) { - $env = new Environment; + $env = new Environment(); $env->parent = $this->env; + $env->parentStore = $this->storeEnv; $env->store = []; $env->block = $block; $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0; $this->env = $env; + $this->storeEnv = null; return $env; } /** * Pop environment + * + * @return void */ protected function popEnv() { + $this->storeEnv = $this->env->parentStore; $this->env = $this->env->parent; } + /** + * Propagate vars from a just poped Env (used in @each and @for) + * + * @param array $store + * @param null|string[] $excludedVars + * + * @return void + */ + protected function backPropagateEnv($store, $excludedVars = null) + { + foreach ($store as $key => $value) { + if (empty($excludedVars) || ! \in_array($key, $excludedVars)) { + $this->set($key, $value, true); + } + } + } + /** * Get store environment * @@ -4139,9 +5151,11 @@ class Compiler * * @param string $name * @param mixed $value - * @param boolean $shadow + * @param bool $shadow * @param \ScssPhp\ScssPhp\Compiler\Environment $env * @param mixed $valueUnreduced + * + * @return void */ protected function set($name, $value, $shadow = false, Environment $env = null, $valueUnreduced = null) { @@ -4165,29 +5179,50 @@ class Compiler * @param mixed $value * @param \ScssPhp\ScssPhp\Compiler\Environment $env * @param mixed $valueUnreduced + * + * @return void */ protected function setExisting($name, $value, Environment $env, $valueUnreduced = null) { $storeEnv = $env; + $specialContentKey = static::$namespaces['special'] . 'content'; $hasNamespace = $name[0] === '^' || $name[0] === '@' || $name[0] === '%'; + $maxDepth = 10000; + for (;;) { - if (array_key_exists($name, $env->store)) { + if ($maxDepth-- <= 0) { + break; + } + + if (\array_key_exists($name, $env->store)) { break; } if (! $hasNamespace && isset($env->marker)) { + if (! empty($env->store[$specialContentKey])) { + $env = $env->store[$specialContentKey]->scope; + continue; + } + + if (! empty($env->declarationScopeParent)) { + $env = $env->declarationScopeParent; + continue; + } else { + $env = $storeEnv; + break; + } + } + + if (isset($env->parentStore)) { + $env = $env->parentStore; + } elseif (isset($env->parent)) { + $env = $env->parent; + } else { $env = $storeEnv; break; } - - if (! isset($env->parent)) { - $env = $storeEnv; - break; - } - - $env = $env->parent; } $env->store[$name] = $value; @@ -4204,6 +5239,8 @@ class Compiler * @param mixed $value * @param \ScssPhp\ScssPhp\Compiler\Environment $env * @param mixed $valueUnreduced + * + * @return void */ protected function setRaw($name, $value, Environment $env, $valueUnreduced = null) { @@ -4217,12 +5254,12 @@ class Compiler /** * Get variable * - * @api + * @internal * * @param string $name - * @param boolean $shouldThrow + * @param bool $shouldThrow * @param \ScssPhp\ScssPhp\Compiler\Environment $env - * @param boolean $unreduced + * @param bool $unreduced * * @return mixed|null */ @@ -4244,7 +5281,7 @@ class Compiler break; } - if (array_key_exists($normalizedName, $env->store)) { + if (\array_key_exists($normalizedName, $env->store)) { if ($unreduced && isset($env->storeUnreduced[$normalizedName])) { return $env->storeUnreduced[$normalizedName]; } @@ -4266,15 +5303,17 @@ class Compiler continue; } - if (! isset($env->parent)) { + if (isset($env->parentStore)) { + $env = $env->parentStore; + } elseif (isset($env->parent)) { + $env = $env->parent; + } else { break; } - - $env = $env->parent; } if ($shouldThrow) { - $this->throwError("Undefined variable \$$name" . ($maxDepth <= 0 ? " (infinite recursion)" : "")); + throw $this->error("Undefined variable \$$name" . ($maxDepth <= 0 ? ' (infinite recursion)' : '')); } // found nothing @@ -4287,17 +5326,19 @@ class Compiler * @param string $name * @param \ScssPhp\ScssPhp\Compiler\Environment $env * - * @return boolean + * @return bool */ protected function has($name, Environment $env = null) { - return ! is_null($this->get($name, false, $env)); + return ! \is_null($this->get($name, false, $env)); } /** * Inject variables * * @param array $args + * + * @return void */ protected function injectVariables(array $args) { @@ -4312,7 +5353,7 @@ class Compiler $name = substr($name, 1); } - if (! $parser->parseValue($strValue, $value)) { + if (!\is_string($strValue) || ! $parser->parseValue($strValue, $value)) { $value = $this->coerceValue($strValue); } @@ -4320,16 +5361,59 @@ class Compiler } } + /** + * Replaces variables. + * + * @param array $variables + * + * @return void + */ + public function replaceVariables(array $variables) + { + $this->registeredVars = []; + $this->addVariables($variables); + } + + /** + * Replaces variables. + * + * @param array $variables + * + * @return void + */ + public function addVariables(array $variables) + { + $triggerWarning = false; + + foreach ($variables as $name => $value) { + if (!$value instanceof Number && !\is_array($value)) { + $triggerWarning = true; + } + + $this->registeredVars[$name] = $value; + } + + if ($triggerWarning) { + @trigger_error('Passing raw values to as custom variables to the Compiler is deprecated. Use "\ScssPhp\ScssPhp\ValueConverter::parseValue" or "\ScssPhp\ScssPhp\ValueConverter::fromPhp" to convert them instead.', E_USER_DEPRECATED); + } + } + /** * Set variables * * @api * * @param array $variables + * + * @return void + * + * @deprecated Use "addVariables" or "replaceVariables" instead. */ public function setVariables(array $variables) { - $this->registeredVars = array_merge($this->registeredVars, $variables); + @trigger_error('The method "setVariables" of the Compiler is deprecated. Use the "addVariables" method for the equivalent behavior or "replaceVariables" if merging with previous variables was not desired.'); + + $this->addVariables($variables); } /** @@ -4338,6 +5422,8 @@ class Compiler * @api * * @param string $name + * + * @return void */ public function unsetVariable($name) { @@ -4359,13 +5445,15 @@ class Compiler /** * Adds to list of parsed files * - * @api + * @internal * - * @param string $path + * @param string|null $path + * + * @return void */ public function addParsedFile($path) { - if (isset($path) && is_file($path)) { + if (! \is_null($path) && is_file($path)) { $this->parsedFiles[realpath($path)] = filemtime($path); } } @@ -4373,12 +5461,12 @@ class Compiler /** * Returns list of parsed files * - * @api - * - * @return array + * @deprecated + * @return array */ public function getParsedFiles() { + @trigger_error('The method "getParsedFiles" of the Compiler is deprecated. Use the "getIncludedFiles" method on the CompilationResult instance returned by compileString() instead. Be careful that the signature of the method is different.', E_USER_DEPRECATED); return $this->parsedFiles; } @@ -4388,10 +5476,12 @@ class Compiler * @api * * @param string|callable $path + * + * @return void */ public function addImportPath($path) { - if (! in_array($path, $this->importPaths)) { + if (! \in_array($path, $this->importPaths)) { $this->importPaths[] = $path; } } @@ -4401,11 +5491,24 @@ class Compiler * * @api * - * @param string|array $path + * @param string|array $path + * + * @return void */ public function setImportPaths($path) { - $this->importPaths = (array) $path; + $paths = (array) $path; + $actualImportPaths = array_filter($paths, function ($path) { + return $path !== ''; + }); + + $this->legacyCwdImportPath = \count($actualImportPaths) !== \count($paths); + + if ($this->legacyCwdImportPath) { + @trigger_error('Passing an empty string in the import paths to refer to the current working directory is deprecated. If that\'s the intended behavior, the value of "getcwd()" should be used directly instead. If this was used for resolving relative imports of the input alongside "chdir" with the source directory, the path of the input file should be passed to "compileString()" instead.', E_USER_DEPRECATED); + } + + $this->importPaths = $actualImportPaths; } /** @@ -4413,11 +5516,43 @@ class Compiler * * @api * - * @param integer $numberPrecision + * @param int $numberPrecision + * + * @return void + * + * @deprecated The number precision is not configurable anymore. The default is enough for all browsers. */ public function setNumberPrecision($numberPrecision) { - Node\Number::$precision = $numberPrecision; + @trigger_error('The number precision is not configurable anymore. ' + . 'The default is enough for all browsers.', E_USER_DEPRECATED); + } + + /** + * Sets the output style. + * + * @api + * + * @param string $style One of the OutputStyle constants + * + * @return void + * + * @phpstan-param OutputStyle::* $style + */ + public function setOutputStyle($style) + { + switch ($style) { + case OutputStyle::EXPANDED: + $this->configuredFormatter = Expanded::class; + break; + + case OutputStyle::COMPRESSED: + $this->configuredFormatter = Compressed::class; + break; + + default: + throw new \InvalidArgumentException(sprintf('Invalid output style "%s".', $style)); + } } /** @@ -4426,10 +5561,21 @@ class Compiler * @api * * @param string $formatterName + * + * @return void + * + * @deprecated Use {@see setOutputStyle} instead. + * + * @phpstan-param class-string $formatterName */ public function setFormatter($formatterName) { - $this->formatter = $formatterName; + if (!\in_array($formatterName, [Expanded::class, Compressed::class], true)) { + @trigger_error('Formatters other than Expanded and Compressed are deprecated.', E_USER_DEPRECATED); + } + @trigger_error('The method "setFormatter" is deprecated. Use "setOutputStyle" instead.', E_USER_DEPRECATED); + + $this->configuredFormatter = $formatterName; } /** @@ -4438,10 +5584,34 @@ class Compiler * @api * * @param string $lineNumberStyle + * + * @return void + * + * @deprecated The line number output is not supported anymore. Use source maps instead. */ public function setLineNumberStyle($lineNumberStyle) { - $this->lineNumberStyle = $lineNumberStyle; + @trigger_error('The line number output is not supported anymore. ' + . 'Use source maps instead.', E_USER_DEPRECATED); + } + + /** + * Configures the handling of non-ASCII outputs. + * + * If $charset is `true`, this will include a `@charset` declaration or a + * UTF-8 [byte-order mark][] if the stylesheet contains any non-ASCII + * characters. Otherwise, it will never include a `@charset` declaration or a + * byte-order mark. + * + * [byte-order mark]: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 + * + * @param bool $charset + * + * @return void + */ + public function setCharset($charset) + { + $this->charset = $charset; } /** @@ -4449,7 +5619,11 @@ class Compiler * * @api * - * @param integer $sourceMap + * @param int $sourceMap + * + * @return void + * + * @phpstan-param self::SOURCE_MAP_* $sourceMap */ public function setSourceMap($sourceMap) { @@ -4462,6 +5636,10 @@ class Compiler * @api * * @param array $sourceMapOptions + * + * @phpstan-param array{sourceRoot?: string, sourceMapFilename?: string|null, sourceMapURL?: string|null, sourceMapWriteTo?: string|null, outputSourceFiles?: bool, sourceMapRootpath?: string, sourceMapBasepath?: string} $sourceMapOptions + * + * @return void */ public function setSourceMapOptions($sourceMapOptions) { @@ -4473,13 +5651,23 @@ class Compiler * * @api * - * @param string $name - * @param callable $func - * @param array $prototype + * @param string $name + * @param callable $callback + * @param string[]|null $argumentDeclaration + * + * @return void */ - public function registerFunction($name, $func, $prototype = null) + public function registerFunction($name, $callback, $argumentDeclaration = null) { - $this->userFunctions[$this->normalizeName($name)] = [$func, $prototype]; + if (self::isNativeFunction($name)) { + @trigger_error(sprintf('The "%s" function is a core sass function. Overriding it with a custom implementation through "%s" is deprecated and won\'t be supported in ScssPhp 2.0 anymore.', $name, __METHOD__), E_USER_DEPRECATED); + } + + if ($argumentDeclaration === null) { + @trigger_error('Omitting the argument declaration when registering custom function is deprecated and won\'t be supported in ScssPhp 2.0 anymore.', E_USER_DEPRECATED); + } + + $this->userFunctions[$this->normalizeName($name)] = [$callback, $argumentDeclaration]; } /** @@ -4488,6 +5676,8 @@ class Compiler * @api * * @param string $name + * + * @return void */ public function unregisterFunction($name) { @@ -4500,9 +5690,15 @@ class Compiler * @api * * @param string $name + * + * @return void + * + * @deprecated Registering additional features is deprecated. */ public function addFeature($name) { + @trigger_error('Registering additional features is deprecated.', E_USER_DEPRECATED); + $this->registeredFeatures[$name] = true; } @@ -4511,12 +5707,28 @@ class Compiler * * @param string $path * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out + * + * @return void */ protected function importFile($path, OutputBlock $out) { + $this->pushCallStack('import ' . $this->getPrettyPath($path)); // see if tree is cached $realPath = realpath($path); + if ($realPath === false) { + $realPath = $path; + } + + if (substr($path, -5) === '.sass') { + $this->sourceIndex = \count($this->sourceNames); + $this->sourceNames[] = $path; + $this->sourceLine = 1; + $this->sourceColumn = 1; + + throw $this->error('The Sass indented syntax is not implemented.'); + } + if (isset($this->importCache[$realPath])) { $this->handleImportLoop($realPath); @@ -4529,62 +5741,261 @@ class Compiler $this->importCache[$realPath] = $tree; } - $pi = pathinfo($path); + $currentDirectory = $this->currentDirectory; + $this->currentDirectory = dirname($path); - array_unshift($this->importPaths, $pi['dirname']); $this->compileChildrenNoReturn($tree->children, $out); - array_shift($this->importPaths); + $this->currentDirectory = $currentDirectory; + $this->popCallStack(); + } + + /** + * Save the imported files with their resolving path context + * + * @param string|null $currentDirectory + * @param string $path + * @param string $filePath + * + * @return void + */ + private function registerImport($currentDirectory, $path, $filePath) + { + $this->resolvedImports[] = ['currentDir' => $currentDirectory, 'path' => $path, 'filePath' => $filePath]; + } + + /** + * Detects whether the import is a CSS import. + * + * For legacy reasons, custom importers are called for those, allowing them + * to replace them with an actual Sass import. However this behavior is + * deprecated. Custom importers are expected to return null when they receive + * a CSS import. + * + * @param string $url + * + * @return bool + */ + public static function isCssImport($url) + { + return 1 === preg_match('~\.css$|^https?://|^//~', $url); } /** * Return the file path for an import url if it exists * - * @api + * @internal * - * @param string $url + * @param string $url + * @param string|null $currentDir * * @return string|null */ - public function findImport($url) + public function findImport($url, $currentDir = null) { - $urls = []; + // Vanilla css and external requests. These are not meant to be Sass imports. + // Callback importers are still called for BC. + if (self::isCssImport($url)) { + foreach ($this->importPaths as $dir) { + if (\is_string($dir)) { + continue; + } - // for "normal" scss imports (ignore vanilla css and external requests) - if (! preg_match('~\.css$|^https?://~', $url)) { - // try both normal and the _partial filename - $urls = [$url, preg_replace('~[^/]+$~', '_\0', $url)]; - } + if (\is_callable($dir)) { + // check custom callback for import path + $file = \call_user_func($dir, $url); - $hasExtension = preg_match('/[.]s?css$/', $url); + if (! \is_null($file)) { + if (\is_array($dir)) { + $callableDescription = (\is_object($dir[0]) ? \get_class($dir[0]) : $dir[0]).'::'.$dir[1]; + } elseif ($dir instanceof \Closure) { + $r = new \ReflectionFunction($dir); + if (false !== strpos($r->name, '{closure}')) { + $callableDescription = sprintf('closure{%s:%s}', $r->getFileName(), $r->getStartLine()); + } elseif ($class = $r->getClosureScopeClass()) { + $callableDescription = $class->name.'::'.$r->name; + } else { + $callableDescription = $r->name; + } + } elseif (\is_object($dir)) { + $callableDescription = \get_class($dir) . '::__invoke'; + } else { + $callableDescription = 'callable'; // Fallback if we don't have a dedicated description + } + @trigger_error(sprintf('Returning a file to import for CSS or external references in custom importer callables is deprecated and will not be supported anymore in ScssPhp 2.0. This behavior is not compliant with the Sass specification. Update your "%s" importer.', $callableDescription), E_USER_DEPRECATED); - foreach ($this->importPaths as $dir) { - if (is_string($dir)) { - // check urls for normal import paths - foreach ($urls as $full) { - $separator = ( - ! empty($dir) && - substr($dir, -1) !== '/' && - substr($full, 0, 1) !== '/' - ) ? '/' : ''; - $full = $dir . $separator . $full; - - if (is_file($file = $full . '.scss') || - ($hasExtension && is_file($file = $full)) - ) { return $file; } } - } elseif (is_callable($dir)) { - // check custom callback for import path - $file = call_user_func($dir, $url); + } + return null; + } - if (! is_null($file)) { + if (!\is_null($currentDir)) { + $relativePath = $this->resolveImportPath($url, $currentDir); + + if (!\is_null($relativePath)) { + return $relativePath; + } + } + + foreach ($this->importPaths as $dir) { + if (\is_string($dir)) { + $path = $this->resolveImportPath($url, $dir); + + if (!\is_null($path)) { + return $path; + } + } elseif (\is_callable($dir)) { + // check custom callback for import path + $file = \call_user_func($dir, $url); + + if (! \is_null($file)) { return $file; } } } - return null; + if ($this->legacyCwdImportPath) { + $path = $this->resolveImportPath($url, getcwd()); + + if (!\is_null($path)) { + @trigger_error('Resolving imports relatively to the current working directory is deprecated. If that\'s the intended behavior, the value of "getcwd()" should be added as an import path explicitly instead. If this was used for resolving relative imports of the input alongside "chdir" with the source directory, the path of the input file should be passed to "compileString()" instead.', E_USER_DEPRECATED); + + return $path; + } + } + + throw $this->error("`$url` file not found for @import"); + } + + /** + * @param string $url + * @param string $baseDir + * + * @return string|null + */ + private function resolveImportPath($url, $baseDir) + { + $path = Path::join($baseDir, $url); + + $hasExtension = preg_match('/.s[ac]ss$/', $url); + + if ($hasExtension) { + return $this->checkImportPathConflicts($this->tryImportPath($path)); + } + + $result = $this->checkImportPathConflicts($this->tryImportPathWithExtensions($path)); + + if (!\is_null($result)) { + return $result; + } + + return $this->tryImportPathAsDirectory($path); + } + + /** + * @param string[] $paths + * + * @return string|null + */ + private function checkImportPathConflicts(array $paths) + { + if (\count($paths) === 0) { + return null; + } + + if (\count($paths) === 1) { + return $paths[0]; + } + + $formattedPrettyPaths = []; + + foreach ($paths as $path) { + $formattedPrettyPaths[] = ' ' . $this->getPrettyPath($path); + } + + throw $this->error("It's not clear which file to import. Found:\n" . implode("\n", $formattedPrettyPaths)); + } + + /** + * @param string $path + * + * @return string[] + */ + private function tryImportPathWithExtensions($path) + { + $result = array_merge( + $this->tryImportPath($path.'.sass'), + $this->tryImportPath($path.'.scss') + ); + + if ($result) { + return $result; + } + + return $this->tryImportPath($path.'.css'); + } + + /** + * @param string $path + * + * @return string[] + */ + private function tryImportPath($path) + { + $partial = dirname($path).'/_'.basename($path); + + $candidates = []; + + if (is_file($partial)) { + $candidates[] = $partial; + } + + if (is_file($path)) { + $candidates[] = $path; + } + + return $candidates; + } + + /** + * @param string $path + * + * @return string|null + */ + private function tryImportPathAsDirectory($path) + { + if (!is_dir($path)) { + return null; + } + + return $this->checkImportPathConflicts($this->tryImportPathWithExtensions($path.'/index')); + } + + /** + * @param string|null $path + * + * @return string + */ + private function getPrettyPath($path) + { + if ($path === null) { + return '(unknown file)'; + } + + $normalizedPath = $path; + $normalizedRootDirectory = $this->rootDirectory.'/'; + + if (\DIRECTORY_SEPARATOR === '\\') { + $normalizedRootDirectory = str_replace('\\', '/', $normalizedRootDirectory); + $normalizedPath = str_replace('\\', '/', $path); + } + + if (0 === strpos($normalizedPath, $normalizedRootDirectory)) { + return substr($path, \strlen($normalizedRootDirectory)); + } + + return $path; } /** @@ -4592,10 +6003,20 @@ class Compiler * * @api * - * @param string $encoding + * @param string|null $encoding + * + * @return void + * + * @deprecated Non-compliant support for other encodings than UTF-8 is deprecated. */ public function setEncoding($encoding) { + if (!$encoding || strtolower($encoding) === 'utf-8') { + @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); + } else { + @trigger_error(sprintf('The "%s" method is deprecated. Parsing will only support UTF-8 in ScssPhp 2.0. The non-UTF-8 parsing of ScssPhp 1.x is not spec compliant.', __METHOD__), E_USER_DEPRECATED); + } + $this->encoding = $encoding; } @@ -4604,17 +6025,37 @@ class Compiler * * @api * - * @param boolean $ignoreErrors + * @param bool $ignoreErrors * * @return \ScssPhp\ScssPhp\Compiler + * + * @deprecated Ignoring Sass errors is not longer supported. */ public function setIgnoreErrors($ignoreErrors) { - $this->ignoreErrors = $ignoreErrors; + @trigger_error('Ignoring Sass errors is not longer supported.', E_USER_DEPRECATED); return $this; } + /** + * Get source position + * + * @api + * + * @return array + * + * @deprecated + */ + public function getSourcePosition() + { + @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); + + $sourceFile = isset($this->sourceNames[$this->sourceIndex]) ? $this->sourceNames[$this->sourceIndex] : ''; + + return [$sourceFile, $this->sourceLine, $this->sourceColumn]; + } + /** * Throw error (exception) * @@ -4622,24 +6063,58 @@ class Compiler * * @param string $msg Message with optional sprintf()-style vararg parameters * + * @return never + * * @throws \ScssPhp\ScssPhp\Exception\CompilerException + * + * @deprecated use "error" and throw the exception in the caller instead. */ public function throwError($msg) { - if ($this->ignoreErrors) { - return; + @trigger_error( + 'The method "throwError" is deprecated. Use "error" and throw the exception in the caller instead', + E_USER_DEPRECATED + ); + + throw $this->error(...func_get_args()); + } + + /** + * Build an error (exception) + * + * @internal + * + * @param string $msg Message with optional sprintf()-style vararg parameters + * @param bool|float|int|string|null ...$args + * + * @return CompilerException + */ + public function error($msg, ...$args) + { + if ($args) { + $msg = sprintf($msg, ...$args); } + if (! $this->ignoreCallStackMessage) { + $msg = $this->addLocationToMessage($msg); + } + + return new CompilerException($msg); + } + + /** + * @param string $msg + * + * @return string + */ + private function addLocationToMessage($msg) + { $line = $this->sourceLine; $column = $this->sourceColumn; $loc = isset($this->sourceNames[$this->sourceIndex]) - ? $this->sourceNames[$this->sourceIndex] . " on line $line, at column $column" - : "line: $line, column: $column"; - - if (func_num_args() > 1) { - $msg = call_user_func_array('sprintf', func_get_args()); - } + ? $this->getPrettyPath($this->sourceNames[$this->sourceIndex]) . " on line $line, at column $column" + : "line: $line, column: $column"; $msg = "$msg: $loc"; @@ -4649,14 +6124,51 @@ class Compiler $msg .= "\nCall Stack:\n" . $callStackMsg; } - throw new CompilerException($msg); + return $msg; + } + + /** + * @param string $functionName + * @param array $ExpectedArgs + * @param int $nbActual + * @return CompilerException + * + * @deprecated + */ + public function errorArgsNumber($functionName, $ExpectedArgs, $nbActual) + { + @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); + + $nbExpected = \count($ExpectedArgs); + + if ($nbActual > $nbExpected) { + return $this->error( + 'Error: Only %d arguments allowed in %s(), but %d were passed.', + $nbExpected, + $functionName, + $nbActual + ); + } else { + $missing = []; + + while (count($ExpectedArgs) && count($ExpectedArgs) > $nbActual) { + array_unshift($missing, array_pop($ExpectedArgs)); + } + + return $this->error( + 'Error: %s() argument%s %s missing.', + $functionName, + count($missing) > 1 ? 's' : '', + implode(', ', $missing) + ); + } } /** * Beautify call stack for output * - * @param boolean $all - * @param null $limit + * @param bool $all + * @param int|null $limit * * @return string */ @@ -4668,15 +6180,15 @@ class Compiler if ($this->callStack) { foreach (array_reverse($this->callStack) as $call) { if ($all || (isset($call['n']) && $call['n'])) { - $msg = "#" . $ncall++ . " " . $call['n'] . " "; + $msg = '#' . $ncall++ . ' ' . $call['n'] . ' '; $msg .= (isset($this->sourceNames[$call[Parser::SOURCE_INDEX]]) - ? $this->sourceNames[$call[Parser::SOURCE_INDEX]] + ? $this->getPrettyPath($this->sourceNames[$call[Parser::SOURCE_INDEX]]) : '(unknown file)'); - $msg .= " on line " . $call[Parser::SOURCE_LINE]; + $msg .= ' on line ' . $call[Parser::SOURCE_LINE]; $callStackMsg[] = $msg; - if (! is_null($limit) && $ncall > $limit) { + if (! \is_null($limit) && $ncall > $limit) { break; } } @@ -4691,6 +6203,8 @@ class Compiler * * @param string $name * + * @return void + * * @throws \Exception */ protected function handleImportLoop($name) @@ -4702,9 +6216,12 @@ class Compiler $file = $this->sourceNames[$env->block->sourceIndex]; + if ($file === null) { + continue; + } + if (realpath($file) === $name) { - $this->throwError('An @import loop has been found: %s imports %s', $file, basename($file)); - break; + throw $this->error('An @import loop has been found: %s imports %s', $file, basename($file)); } } } @@ -4712,100 +6229,86 @@ class Compiler /** * Call SCSS @function * - * @param string $name - * @param array $argValues - * @param array $returnValue + * @param CallableBlock|null $func + * @param array $argValues * - * @return boolean Returns true if returnValue is set; otherwise, false + * @return array|Number */ - protected function callScssFunction($name, $argValues, &$returnValue) + protected function callScssFunction($func, $argValues) { - $func = $this->get(static::$namespaces['function'] . $name, false); - if (! $func) { - return false; + return static::$defaultValue; } + $name = $func->name; $this->pushEnv(); - $storeEnv = $this->storeEnv; - $this->storeEnv = $this->env; - // set the args if (isset($func->args)) { $this->applyArguments($func->args, $argValues); } // throw away lines and children - $tmp = new OutputBlock; + $tmp = new OutputBlock(); $tmp->lines = []; $tmp->children = []; $this->env->marker = 'function'; + if (! empty($func->parentEnv)) { $this->env->declarationScopeParent = $func->parentEnv; } else { - $this->throwError("@function $name() without parentEnv"); + throw $this->error("@function $name() without parentEnv"); } - $ret = $this->compileChildren($func->children, $tmp, $this->env->marker . " " . $name); - - $this->storeEnv = $storeEnv; + $ret = $this->compileChildren($func->children, $tmp, $this->env->marker . ' ' . $name); $this->popEnv(); - $returnValue = ! isset($ret) ? static::$defaultValue : $ret; - - return true; + return ! isset($ret) ? static::$defaultValue : $ret; } /** * Call built-in and registered (PHP) functions * * @param string $name + * @param callable $function + * @param array $prototype * @param array $args - * @param array $returnValue * - * @return boolean Returns true if returnValue is set; otherwise, false + * @return array|Number|null */ - protected function callNativeFunction($name, $args, &$returnValue) + protected function callNativeFunction($name, $function, $prototype, $args) { - // try a lib function - $name = $this->normalizeName($name); + $libName = (is_array($function) ? end($function) : null); + $sorted_kwargs = $this->sortNativeFunctionArgs($libName, $prototype, $args); - if (isset($this->userFunctions[$name])) { - // see if we can find a user function - list($f, $prototype) = $this->userFunctions[$name]; - } elseif (($f = $this->getBuiltinFunction($name)) && is_callable($f)) { - $libName = $f[1]; - $prototype = isset(static::$$libName) ? static::$$libName : null; - } else { - return false; + if (\is_null($sorted_kwargs)) { + return null; } + @list($sorted, $kwargs) = $sorted_kwargs; - @list($sorted, $kwargs) = $this->sortNativeFunctionArgs($libName, $prototype, $args); - - if ($name !== 'if' && $name !== 'call') { - $inExp = true; - - if ($name === 'join') { - $inExp = false; - } - + if ($name !== 'if') { foreach ($sorted as &$val) { - $val = $this->reduce($val, $inExp); + if ($val !== null) { + $val = $this->reduce($val, true); + } } } - $returnValue = call_user_func($f, $sorted, $kwargs); + $returnValue = \call_user_func($function, $sorted, $kwargs); if (! isset($returnValue)) { - return false; + return null; } - $returnValue = $this->coerceValue($returnValue); + if (\is_array($returnValue) || $returnValue instanceof Number) { + return $returnValue; + } - return true; + @trigger_error(sprintf('Returning a PHP value from the "%s" custom function is deprecated. A sass value must be returned instead.', $name), E_USER_DEPRECATED); + + return $this->coerceValue($returnValue); } /** @@ -4817,6 +6320,22 @@ class Compiler */ protected function getBuiltinFunction($name) { + $libName = self::normalizeNativeFunctionName($name); + return [$this, $libName]; + } + + /** + * Normalize native function name + * + * @internal + * + * @param string $name + * + * @return string + */ + public static function normalizeNativeFunctionName($name) + { + $name = str_replace("-", "_", $name); $libName = 'lib' . preg_replace_callback( '/_(.)/', function ($m) { @@ -4824,18 +6343,31 @@ class Compiler }, ucfirst($name) ); + return $libName; + } - return [$this, $libName]; + /** + * Check if a function is a native built-in scss function, for css parsing + * + * @internal + * + * @param string $name + * + * @return bool + */ + public static function isNativeFunction($name) + { + return method_exists(Compiler::class, self::normalizeNativeFunctionName($name)); } /** * Sorts keyword arguments * * @param string $functionName - * @param array $prototypes + * @param array|null $prototypes * @param array $args * - * @return array + * @return array|null */ protected function sortNativeFunctionArgs($functionName, $prototypes, $args) { @@ -4845,16 +6377,18 @@ class Compiler $keyArgs = []; $posArgs = []; + if (\is_array($args) && \count($args) && \end($args) === static::$null) { + array_pop($args); + } + // separate positional and keyword arguments foreach ($args as $arg) { list($key, $value) = $arg; - $key = $key[1]; - - if (empty($key)) { + if (empty($key) or empty($key[1])) { $posArgs[] = empty($arg[2]) ? $value : $arg; } else { - $keyArgs[$key] = $value; + $keyArgs[$key[1]] = $value; } } @@ -4862,209 +6396,359 @@ class Compiler } // specific cases ? - if (in_array($functionName, ['libRgb', 'libRgba', 'libHsl', 'libHsla'])) { + if (\in_array($functionName, ['libRgb', 'libRgba', 'libHsl', 'libHsla'])) { // notation 100 127 255 / 0 is in fact a simple list of 4 values foreach ($args as $k => $arg) { - if ($arg[1][0] === Type::T_LIST && count($arg[1][2]) === 3) { - $last = end($arg[1][2]); - - if ($last[0] === Type::T_EXPRESSION && $last[1] === '/') { - array_pop($arg[1][2]); - $arg[1][2][] = $last[2]; - $arg[1][2][] = $last[3]; - $args[$k] = $arg; - } + if (!isset($arg[1])) { + continue; // This happens when using a trailing comma + } + if ($arg[1][0] === Type::T_LIST && \count($arg[1][2]) === 3) { + $args[$k][1][2] = $this->extractSlashAlphaInColorFunction($arg[1][2]); } } } - $finalArgs = []; + list($positionalArgs, $namedArgs, $names, $separator, $hasSplat) = $this->evaluateArguments($args, false); - if (! is_array(reset($prototypes))) { + if (! \is_array(reset($prototypes))) { $prototypes = [$prototypes]; } + $parsedPrototypes = array_map([$this, 'parseFunctionPrototype'], $prototypes); + assert(!empty($parsedPrototypes)); + $matchedPrototype = $this->selectFunctionPrototype($parsedPrototypes, \count($positionalArgs), $names); + + $this->verifyPrototype($matchedPrototype, \count($positionalArgs), $names, $hasSplat); + + $vars = $this->applyArgumentsToDeclaration($matchedPrototype, $positionalArgs, $namedArgs, $separator); + + $finalArgs = []; $keyArgs = []; - // trying each prototypes - $prototypeHasMatch = false; - $exceptionMessage = ''; + foreach ($matchedPrototype['arguments'] as $argument) { + list($normalizedName, $originalName, $default) = $argument; - foreach ($prototypes as $prototype) { - $argDef = []; - - foreach ($prototype as $i => $p) { - $default = null; - $p = explode(':', $p, 2); - $name = array_shift($p); - - if (count($p)) { - $p = trim(reset($p)); - - if ($p === 'null') { - // differentiate this null from the static::$null - $default = [Type::T_KEYWORD, 'null']; - } else { - if (is_null($parser)) { - $parser = $this->parserFactory(__METHOD__); - } - - $parser->parseValue($p, $default); - } - } - - $isVariable = false; - - if (substr($name, -3) === '...') { - $isVariable = true; - $name = substr($name, 0, -3); - } - - $argDef[] = [$name, $default, $isVariable]; + if (isset($vars[$normalizedName])) { + $value = $vars[$normalizedName]; + } else { + $value = $default; } - try { - $vars = $this->applyArguments($argDef, $args, false, false); - - // ensure all args are populated - foreach ($prototype as $i => $p) { - $name = explode(':', $p)[0]; - - if (! isset($finalArgs[$i])) { - $finalArgs[$i] = null; - } - } - - // apply positional args - foreach (array_values($vars) as $i => $val) { - $finalArgs[$i] = $val; - } - - $keyArgs = array_merge($keyArgs, $vars); - $prototypeHasMatch = true; - - // overwrite positional args with keyword args - foreach ($prototype as $i => $p) { - $name = explode(':', $p)[0]; - - if (isset($keyArgs[$name])) { - $finalArgs[$i] = $keyArgs[$name]; - } - - // special null value as default: translate to real null here - if ($finalArgs[$i] === [Type::T_KEYWORD, 'null']) { - $finalArgs[$i] = null; - } - } - // should we break if this prototype seems fulfilled? - } catch (CompilerException $e) { - $exceptionMessage = $e->getMessage(); + // special null value as default: translate to real null here + if ($value === [Type::T_KEYWORD, 'null']) { + $value = null; } + + $finalArgs[] = $value; + $keyArgs[$originalName] = $value; } - if ($exceptionMessage && ! $prototypeHasMatch) { - $this->throwError($exceptionMessage); + if ($matchedPrototype['rest_argument'] !== null) { + $value = $vars[$matchedPrototype['rest_argument']]; + + $finalArgs[] = $value; + $keyArgs[$matchedPrototype['rest_argument']] = $value; } return [$finalArgs, $keyArgs]; } /** - * Apply argument values per definition + * Parses a function prototype to the internal representation of arguments. * - * @param array $argDef - * @param array $argValues - * @param boolean $storeInEnv - * @param boolean $reduce - * only used if $storeInEnv = false + * The input is an array of strings describing each argument, as supported + * in {@see registerFunction}. Argument names don't include the `$`. + * The output contains the list of positional argument, with their normalized + * name (underscores are replaced by dashes), their original name (to be used + * in case of error reporting) and their default value. The output also contains + * the normalized name of the rest argument, or null if the function prototype + * is not variadic. + * + * @param string[] $prototype + * + * @return array + * @phpstan-return array{arguments: list, rest_argument: string|null} + */ + private function parseFunctionPrototype(array $prototype) + { + static $parser = null; + + $arguments = []; + $restArgument = null; + + foreach ($prototype as $p) { + if (null !== $restArgument) { + throw new \InvalidArgumentException('The argument declaration is invalid. The rest argument must be the last one.'); + } + + $default = null; + $p = explode(':', $p, 2); + $name = str_replace('_', '-', $p[0]); + + if (isset($p[1])) { + $defaultSource = trim($p[1]); + + if ($defaultSource === 'null') { + // differentiate this null from the static::$null + $default = [Type::T_KEYWORD, 'null']; + } else { + if (\is_null($parser)) { + $parser = $this->parserFactory(__METHOD__); + } + + $parser->parseValue($defaultSource, $default); + } + } + + if (substr($name, -3) === '...') { + $restArgument = substr($name, 0, -3); + } else { + $arguments[] = [$name, $p[0], $default]; + } + } + + return [ + 'arguments' => $arguments, + 'rest_argument' => $restArgument, + ]; + } + + /** + * Returns the function prototype for the given positional and named arguments. + * + * If no exact match is found, finds the closest approximation. Note that this + * doesn't guarantee that $positional and $names are valid for the returned + * prototype. + * + * @param array[] $prototypes + * @param int $positional + * @param array $names A set of names, as both keys and values * * @return array * - * @throws \Exception + * @phpstan-param non-empty-list, rest_argument: string|null}> $prototypes + * @phpstan-return array{arguments: list, rest_argument: string|null} */ - protected function applyArguments($argDef, $argValues, $storeInEnv = true, $reduce = true) + private function selectFunctionPrototype(array $prototypes, $positional, array $names) { - $output = []; - if (is_array($argValues) && count($argValues) && end($argValues) === static::$null) { - array_pop($argValues); + $fuzzyMatch = null; + $minMismatchDistance = null; + + foreach ($prototypes as $prototype) { + // Ideally, find an exact match. + if ($this->checkPrototypeMatches($prototype, $positional, $names)) { + return $prototype; + } + + $mismatchDistance = \count($prototype['arguments']) - $positional; + + if ($minMismatchDistance !== null) { + if (abs($mismatchDistance) > abs($minMismatchDistance)) { + continue; + } + + // If two overloads have the same mismatch distance, favor the overload + // that has more arguments. + if (abs($mismatchDistance) === abs($minMismatchDistance) && $mismatchDistance < 0) { + continue; + } + } + + $minMismatchDistance = $mismatchDistance; + $fuzzyMatch = $prototype; } - if ($storeInEnv) { - $storeEnv = $this->getStoreEnv(); + return $fuzzyMatch; + } - $env = new Environment; - $env->store = $storeEnv->store; + /** + * Checks whether the argument invocation matches the callable prototype. + * + * The rules are similar to {@see verifyPrototype}. The boolean return value + * avoids the overhead of building and catching exceptions when the reason of + * not matching the prototype does not need to be known. + * + * @param array $prototype + * @param int $positional + * @param array $names + * + * @return bool + * + * @phpstan-param array{arguments: list, rest_argument: string|null} $prototype + */ + private function checkPrototypeMatches(array $prototype, $positional, array $names) + { + $nameUsed = 0; + + foreach ($prototype['arguments'] as $i => $argument) { + list ($name, $originalName, $default) = $argument; + + if ($i < $positional) { + if (isset($names[$name])) { + return false; + } + } elseif (isset($names[$name])) { + $nameUsed++; + } elseif ($default === null) { + return false; + } } - $hasVariable = false; - $args = []; - - foreach ($argDef as $i => $arg) { - list($name, $default, $isVariable) = $argDef[$i]; - - $args[$name] = [$i, $name, $default, $isVariable]; - $hasVariable |= $isVariable; + if ($prototype['rest_argument'] !== null) { + return true; } - $splatSeparator = null; - $keywordArgs = []; - $deferredKeywordArgs = []; - $remaining = []; - $hasKeywordArgument = false; + if ($positional > \count($prototype['arguments'])) { + return false; + } - // assign the keyword args - foreach ((array) $argValues as $arg) { - if (! empty($arg[0])) { + if ($nameUsed < \count($names)) { + return false; + } + + return true; + } + + /** + * Verifies that the argument invocation is valid for the callable prototype. + * + * @param array $prototype + * @param int $positional + * @param array $names + * @param bool $hasSplat + * + * @return void + * + * @throws SassScriptException + * + * @phpstan-param array{arguments: list, rest_argument: string|null} $prototype + */ + private function verifyPrototype(array $prototype, $positional, array $names, $hasSplat) + { + $nameUsed = 0; + + foreach ($prototype['arguments'] as $i => $argument) { + list ($name, $originalName, $default) = $argument; + + if ($i < $positional) { + if (isset($names[$name])) { + throw new SassScriptException(sprintf('Argument $%s was passed both by position and by name.', $originalName)); + } + } elseif (isset($names[$name])) { + $nameUsed++; + } elseif ($default === null) { + throw new SassScriptException(sprintf('Missing argument $%s', $originalName)); + } + } + + if ($prototype['rest_argument'] !== null) { + return; + } + + if ($positional > \count($prototype['arguments'])) { + $message = sprintf( + 'Only %d %sargument%s allowed, but %d %s passed.', + \count($prototype['arguments']), + empty($names) ? '' : 'positional ', + \count($prototype['arguments']) === 1 ? '' : 's', + $positional, + $positional === 1 ? 'was' : 'were' + ); + if (!$hasSplat) { + throw new SassScriptException($message); + } + + $message = $this->addLocationToMessage($message); + $message .= "\nThis will be an error in future versions of Sass."; + $this->logger->warn($message, true); + } + + if ($nameUsed < \count($names)) { + $unknownNames = array_values(array_diff($names, array_column($prototype['arguments'], 0))); + $lastName = array_pop($unknownNames); + $message = sprintf( + 'No argument%s named $%s%s.', + $unknownNames ? 's' : '', + $unknownNames ? implode(', $', $unknownNames) . ' or $' : '', + $lastName + ); + throw new SassScriptException($message); + } + } + + /** + * Evaluates the argument from the invocation. + * + * This returns several things about this invocation: + * - the list of positional arguments + * - the map of named arguments, indexed by normalized names + * - the set of names used in the arguments (that's an array using the normalized names as keys for O(1) access) + * - the separator used by the list using the splat operator, if any + * - a boolean indicator whether any splat argument (list or map) was used, to support the incomplete error reporting. + * + * @param array[] $args + * @param bool $reduce Whether arguments should be reduced to their value + * + * @return array + * + * @throws SassScriptException + * + * @phpstan-return array{0: list, 1: array, 2: array, 3: string|null, 4: bool} + */ + private function evaluateArguments(array $args, $reduce = true) + { + // this represents trailing commas + if (\count($args) && end($args) === static::$null) { + array_pop($args); + } + + $splatSeparator = null; + $keywordArgs = []; + $names = []; + $positionalArgs = []; + $hasKeywordArgument = false; + $hasSplat = false; + + foreach ($args as $arg) { + if (!empty($arg[0])) { $hasKeywordArgument = true; - $name = $arg[0][1]; - if (! isset($args[$name])) { - foreach (array_keys($args) as $an) { - if (str_replace("_", "-", $an) === str_replace("_", "-", $name)) { - $name = $an; - break; - } - } + assert(\is_string($arg[0][1])); + $name = str_replace('_', '-', $arg[0][1]); + + if (isset($keywordArgs[$name])) { + throw new SassScriptException(sprintf('Duplicate named argument $%s.', $arg[0][1])); } - if (! isset($args[$name]) || $args[$name][3]) { - if ($hasVariable) { - $deferredKeywordArgs[$name] = $arg[1]; - } else { - $this->throwError("Mixin or function doesn't have an argument named $%s.", $arg[0][1]); - break; - } - } elseif ($args[$name][0] < count($remaining)) { - $this->throwError("The argument $%s was passed both by position and by name.", $arg[0][1]); - break; - } else { - $keywordArgs[$name] = $arg[1]; - } - } elseif ($arg[2] === true) { + + $keywordArgs[$name] = $this->maybeReduce($reduce, $arg[1]); + $names[$name] = $name; + } elseif (! empty($arg[2])) { + // $arg[2] means a var followed by ... in the arg ($list... ) $val = $this->reduce($arg[1], true); + $hasSplat = true; if ($val[0] === Type::T_LIST) { - foreach ($val[2] as $name => $item) { - if (! is_numeric($name)) { - if (! isset($args[$name])) { - foreach (array_keys($args) as $an) { - if (str_replace("_", "-", $an) === str_replace("_", "-", $name)) { - $name = $an; - break; - } - } + foreach ($val[2] as $item) { + if (\is_null($splatSeparator)) { + $splatSeparator = $val[1]; + } + + $positionalArgs[] = $this->maybeReduce($reduce, $item); + } + + if (isset($val[3]) && \is_array($val[3])) { + foreach ($val[3] as $name => $item) { + assert(\is_string($name)); + + $normalizedName = str_replace('_', '-', $name); + + if (isset($keywordArgs[$normalizedName])) { + throw new SassScriptException(sprintf('Duplicate named argument $%s.', $name)); } - if ($hasVariable) { - $deferredKeywordArgs[$name] = $item; - } else { - $keywordArgs[$name] = $item; - } - } else { - if (is_null($splatSeparator)) { - $splatSeparator = $val[1]; - } - - $remaining[] = $item; + $keywordArgs[$normalizedName] = $this->maybeReduce($reduce, $item); + $names[$normalizedName] = $normalizedName; + $hasKeywordArgument = true; } } } elseif ($val[0] === Type::T_MAP) { @@ -5073,62 +6757,121 @@ class Compiler $item = $val[2][$i]; if (! is_numeric($name)) { - if (! isset($args[$name])) { - foreach (array_keys($args) as $an) { - if (str_replace("_", "-", $an) === str_replace("_", "-", $name)) { - $name = $an; - break; - } - } + $normalizedName = str_replace('_', '-', $name); + + if (isset($keywordArgs[$normalizedName])) { + throw new SassScriptException(sprintf('Duplicate named argument $%s.', $name)); } - if ($hasVariable) { - $deferredKeywordArgs[$name] = $item; - } else { - $keywordArgs[$name] = $item; - } + $keywordArgs[$normalizedName] = $this->maybeReduce($reduce, $item); + $names[$normalizedName] = $normalizedName; + $hasKeywordArgument = true; } else { - if (is_null($splatSeparator)) { + if (\is_null($splatSeparator)) { $splatSeparator = $val[1]; } - $remaining[] = $item; + $positionalArgs[] = $this->maybeReduce($reduce, $item); } } - } else { - $remaining[] = $val; + } elseif ($val[0] !== Type::T_NULL) { // values other than null are treated a single-element lists, while null is the empty list + $positionalArgs[] = $this->maybeReduce($reduce, $val); } } elseif ($hasKeywordArgument) { - $this->throwError('Positional arguments must come before keyword arguments.'); - break; + throw new SassScriptException('Positional arguments must come before keyword arguments.'); } else { - $remaining[] = $arg[1]; + $positionalArgs[] = $this->maybeReduce($reduce, $arg[1]); } } - foreach ($args as $arg) { - list($i, $name, $default, $isVariable) = $arg; + return [$positionalArgs, $keywordArgs, $names, $splatSeparator, $hasSplat]; + } + + /** + * @param bool $reduce + * @param array|Number $value + * + * @return array|Number + */ + private function maybeReduce($reduce, $value) + { + if ($reduce) { + return $this->reduce($value, true); + } + + return $value; + } + + /** + * Apply argument values per definition + * + * @param array[] $argDef + * @param array|null $argValues + * @param bool $storeInEnv + * @param bool $reduce only used if $storeInEnv = false + * + * @return array + * + * @phpstan-param list $argDef + * + * @throws \Exception + */ + protected function applyArguments($argDef, $argValues, $storeInEnv = true, $reduce = true) + { + $output = []; + + if (\is_null($argValues)) { + $argValues = []; + } + + if ($storeInEnv) { + $storeEnv = $this->getStoreEnv(); + + $env = new Environment(); + $env->store = $storeEnv->store; + } + + $prototype = ['arguments' => [], 'rest_argument' => null]; + $originalRestArgumentName = null; + + foreach ($argDef as $arg) { + list($name, $default, $isVariable) = $arg; + $normalizedName = str_replace('_', '-', $name); if ($isVariable) { - $val = [Type::T_LIST, is_null($splatSeparator) ? ',' : $splatSeparator , [], $isVariable]; - - for ($count = count($remaining); $i < $count; $i++) { - $val[2][] = $remaining[$i]; - } - - foreach ($deferredKeywordArgs as $itemName => $item) { - $val[2][$itemName] = $item; - } - } elseif (isset($remaining[$i])) { - $val = $remaining[$i]; - } elseif (isset($keywordArgs[$name])) { - $val = $keywordArgs[$name]; - } elseif (! empty($default)) { - continue; + $originalRestArgumentName = $name; + $prototype['rest_argument'] = $normalizedName; } else { - $this->throwError("Missing argument $name"); - break; + $prototype['arguments'][] = [$normalizedName, $name, !empty($default) ? $default : null]; } + } + + list($positionalArgs, $namedArgs, $names, $splatSeparator, $hasSplat) = $this->evaluateArguments($argValues, $reduce); + + $this->verifyPrototype($prototype, \count($positionalArgs), $names, $hasSplat); + + $vars = $this->applyArgumentsToDeclaration($prototype, $positionalArgs, $namedArgs, $splatSeparator); + + foreach ($prototype['arguments'] as $argument) { + list($normalizedName, $name) = $argument; + + if (!isset($vars[$normalizedName])) { + continue; + } + + $val = $vars[$normalizedName]; + + if ($storeInEnv) { + $this->set($name, $this->reduce($val, true), true, $env); + } else { + $output[$name] = ($reduce ? $this->reduce($val, true) : $val); + } + } + + if ($prototype['rest_argument'] !== null) { + assert($originalRestArgumentName !== null); + $name = $originalRestArgumentName; + $val = $vars[$prototype['rest_argument']]; if ($storeInEnv) { $this->set($name, $this->reduce($val, true), true, $env); @@ -5141,12 +6884,13 @@ class Compiler $storeEnv->store = $env->store; } - foreach ($args as $arg) { - list($i, $name, $default, $isVariable) = $arg; + foreach ($prototype['arguments'] as $argument) { + list($normalizedName, $name, $default) = $argument; - if ($isVariable || isset($remaining[$i]) || isset($keywordArgs[$name]) || empty($default)) { + if (isset($vars[$normalizedName])) { continue; } + assert($default !== null); if ($storeInEnv) { $this->set($name, $this->reduce($default, true), true); @@ -5158,29 +6902,90 @@ class Compiler return $output; } + /** + * Apply argument values per definition. + * + * This method assumes that the arguments are valid for the provided prototype. + * The validation with {@see verifyPrototype} must have been run before calling + * it. + * Arguments are returned as a map from the normalized argument names to the + * value. Additional arguments are collected in a sass argument list available + * under the name of the rest argument in the result. + * + * Defaults are not applied as they are resolved in a different environment. + * + * @param array $prototype + * @param array $positionalArgs + * @param array $namedArgs + * @param string|null $splatSeparator + * + * @return array + * + * @phpstan-param array{arguments: list, rest_argument: string|null} $prototype + */ + private function applyArgumentsToDeclaration(array $prototype, array $positionalArgs, array $namedArgs, $splatSeparator) + { + $output = []; + $minLength = min(\count($positionalArgs), \count($prototype['arguments'])); + + for ($i = 0; $i < $minLength; $i++) { + list($name) = $prototype['arguments'][$i]; + $val = $positionalArgs[$i]; + + $output[$name] = $val; + } + + $restNamed = $namedArgs; + + for ($i = \count($positionalArgs); $i < \count($prototype['arguments']); $i++) { + $argument = $prototype['arguments'][$i]; + list($name) = $argument; + + if (isset($namedArgs[$name])) { + $val = $namedArgs[$name]; + unset($restNamed[$name]); + } else { + continue; + } + + $output[$name] = $val; + } + + if ($prototype['rest_argument'] !== null) { + $name = $prototype['rest_argument']; + $rest = array_values(array_slice($positionalArgs, \count($prototype['arguments']))); + + $val = [Type::T_LIST, \is_null($splatSeparator) ? ',' : $splatSeparator , $rest, $restNamed]; + + $output[$name] = $val; + } + + return $output; + } + /** * Coerce a php value into a scss one * * @param mixed $value * - * @return array|\ScssPhp\ScssPhp\Node\Number + * @return array|Number */ protected function coerceValue($value) { - if (is_array($value) || $value instanceof \ArrayAccess) { + if (\is_array($value) || $value instanceof Number) { return $value; } - if (is_bool($value)) { + if (\is_bool($value)) { return $this->toBool($value); } - if (is_null($value)) { + if (\is_null($value)) { return static::$null; } if (is_numeric($value)) { - return new Node\Number($value, ''); + return new Number($value, ''); } if ($value === '') { @@ -5198,80 +7003,102 @@ class Compiler } /** - * Coerce something to map + * Tries to convert an item to a Sass map * - * @param array $item + * @param Number|array $item * - * @return array + * @return array|null */ - protected function coerceMap($item) + private function tryMap($item) { + if ($item instanceof Number) { + return null; + } + if ($item[0] === Type::T_MAP) { return $item; } - if ($item[0] === static::$emptyList[0] - && $item[1] === static::$emptyList[1] - && $item[2] === static::$emptyList[2]) { + if ( + $item[0] === Type::T_LIST && + $item[2] === [] + ) { return static::$emptyMap; } - return [Type::T_MAP, [$item], [static::$null]]; + return null; + } + + /** + * Coerce something to map + * + * @param array|Number $item + * + * @return array|Number + */ + protected function coerceMap($item) + { + $map = $this->tryMap($item); + + if ($map !== null) { + return $map; + } + + return $item; } /** * Coerce something to list * - * @param array $item - * @param string $delim + * @param array|Number $item + * @param string $delim + * @param bool $removeTrailingNull * * @return array */ - protected function coerceList($item, $delim = ',') + protected function coerceList($item, $delim = ',', $removeTrailingNull = false) { - if (isset($item) && $item[0] === Type::T_LIST) { + if ($item instanceof Number) { + return [Type::T_LIST, '', [$item]]; + } + + if ($item[0] === Type::T_LIST) { + // remove trailing null from the list + if ($removeTrailingNull && end($item[2]) === static::$null) { + array_pop($item[2]); + } + return $item; } - if (isset($item) && $item[0] === Type::T_MAP) { + if ($item[0] === Type::T_MAP) { $keys = $item[1]; $values = $item[2]; $list = []; - for ($i = 0, $s = count($keys); $i < $s; $i++) { + for ($i = 0, $s = \count($keys); $i < $s; $i++) { $key = $keys[$i]; $value = $values[$i]; - switch ($key[0]) { - case Type::T_LIST: - case Type::T_MAP: - case Type::T_STRING: - break; - - default: - $key = [Type::T_KEYWORD, $this->compileStringContent($this->coerceString($key))]; - break; - } - $list[] = [ Type::T_LIST, - '', + ' ', [$key, $value] ]; } - return [Type::T_LIST, ',', $list]; + return [Type::T_LIST, $list ? ',' : '', $list]; } - return [Type::T_LIST, $delim, ! isset($item) ? []: [$item]]; + return [Type::T_LIST, '', [$item]]; } /** * Coerce color for expression * - * @param array $value + * @param array|Number $value * - * @return array|null + * @return array|Number */ protected function coerceForExpression($value) { @@ -5285,12 +7112,17 @@ class Compiler /** * Coerce value to color * - * @param array $value + * @param array|Number $value + * @param bool $inRGBFunction * * @return array|null */ protected function coerceColor($value, $inRGBFunction = false) { + if ($value instanceof Number) { + return null; + } + switch ($value[0]) { case Type::T_COLOR: for ($i = 1; $i <= 3; $i++) { @@ -5321,7 +7153,7 @@ class Compiler case Type::T_LIST: if ($inRGBFunction) { - if (count($value[2]) == 3 || count($value[2]) == 4) { + if (\count($value[2]) == 3 || \count($value[2]) == 4) { $color = $value[2]; array_unshift($color, Type::T_COLOR); @@ -5332,16 +7164,17 @@ class Compiler return null; case Type::T_KEYWORD: - if (! is_string($value[1])) { + if (! \is_string($value[1])) { return null; } $name = strtolower($value[1]); + // hexa color? if (preg_match('/^#([0-9a-f]+)$/i', $name, $m)) { - $nofValues = strlen($m[1]); + $nofValues = \strlen($m[1]); - if (in_array($nofValues, [3, 4, 6, 8])) { + if (\in_array($nofValues, [3, 4, 6, 8])) { $nbChannels = 3; $color = []; $num = hexdec($m[1]); @@ -5375,7 +7208,7 @@ class Compiler if ($color[3] === 255) { $color[3] = 1; // fully opaque } else { - $color[3] = round($color[3] / 255, 3); + $color[3] = round($color[3] / 255, Number::PRECISION); } } @@ -5398,10 +7231,10 @@ class Compiler } /** - * @param integer|\ScssPhp\ScssPhp\Node\Number $value - * @param boolean $isAlpha + * @param int|Number $value + * @param bool $isAlpha * - * @return integer|mixed + * @return int|mixed */ protected function compileRGBAValue($value, $isAlpha = false) { @@ -5413,44 +7246,35 @@ class Compiler } /** - * @param mixed $value - * @param integer|float $min - * @param integer|float $max - * @param boolean $isInt - * @param boolean $clamp - * @param boolean $modulo + * @param mixed $value + * @param int|float $min + * @param int|float $max + * @param bool $isInt * - * @return integer|mixed + * @return int|mixed */ - protected function compileColorPartValue($value, $min, $max, $isInt = true, $clamp = true, $modulo = false) + protected function compileColorPartValue($value, $min, $max, $isInt = true) { if (! is_numeric($value)) { - if (is_array($value)) { + if (\is_array($value)) { $reduced = $this->reduce($value); - if (is_object($reduced) && $value->type === Type::T_NUMBER) { + if ($reduced instanceof Number) { $value = $reduced; } } - if (is_object($value) && $value->type === Type::T_NUMBER) { - $num = $value->dimension; - - if (count($value->units)) { - $unit = array_keys($value->units); - $unit = reset($unit); - - switch ($unit) { - case '%': - $num *= $max / 100; - break; - default: - break; - } + if ($value instanceof Number) { + if ($value->unitless()) { + $num = $value->getDimension(); + } elseif ($value->hasUnit('%')) { + $num = $max * $value->getDimension() / 100; + } else { + throw $this->error('Expected %s to have no units or "%%".', $value); } $value = $num; - } elseif (is_array($value)) { + } elseif (\is_array($value)) { $value = $this->compileValue($value); } } @@ -5460,18 +7284,7 @@ class Compiler $value = round($value); } - if ($clamp) { - $value = min($max, max($min, $value)); - } - - if ($modulo) { - $value = $value % $max; - - // still negative? - while ($value < $min) { - $value += $max; - } - } + $value = min($max, max($min, $value)); return $value; } @@ -5482,34 +7295,72 @@ class Compiler /** * Coerce value to string * - * @param array $value + * @param array|Number $value * - * @return array|null + * @return array */ protected function coerceString($value) { if ($value[0] === Type::T_STRING) { + assert(\is_array($value)); + return $value; } return [Type::T_STRING, '', [$this->compileValue($value)]]; } + /** + * Assert value is a string + * + * This method deals with internal implementation details of the value + * representation where unquoted strings can sometimes be stored under + * other types. + * The returned value is always using the T_STRING type. + * + * @api + * + * @param array|Number $value + * @param string|null $varName + * + * @return array + * + * @throws SassScriptException + */ + public function assertString($value, $varName = null) + { + // case of url(...) parsed a a function + if ($value[0] === Type::T_FUNCTION) { + $value = $this->coerceString($value); + } + + if (! \in_array($value[0], [Type::T_STRING, Type::T_KEYWORD])) { + $value = $this->compileValue($value); + throw SassScriptException::forArgument("$value is not a string.", $varName); + } + + return $this->coerceString($value); + } + /** * Coerce value to a percentage * - * @param array $value + * @param array|Number $value * - * @return integer|float + * @return int|float + * + * @deprecated */ protected function coercePercent($value) { - if ($value[0] === Type::T_NUMBER) { - if (! empty($value[2]['%'])) { - return $value[1] / 100; + @trigger_error(sprintf('"%s" is deprecated since 1.7.0.', __METHOD__), E_USER_DEPRECATED); + + if ($value instanceof Number) { + if ($value->hasUnit('%')) { + return $value->getDimension() / 100; } - return $value[1]; + return $value->getDimension(); } return 0; @@ -5520,21 +7371,24 @@ class Compiler * * @api * - * @param array $value + * @param array|Number $value + * @param string|null $varName * * @return array * - * @throws \Exception + * @throws SassScriptException */ - public function assertMap($value) + public function assertMap($value, $varName = null) { - $value = $this->coerceMap($value); + $map = $this->tryMap($value); - if ($value[0] !== Type::T_MAP) { - $this->throwError('expecting map, %s received', $value[0]); + if ($map === null) { + $value = $this->compileValue($value); + + throw SassScriptException::forArgument("$value is not a map.", $varName); } - return $value; + return $map; } /** @@ -5542,7 +7396,7 @@ class Compiler * * @api * - * @param array $value + * @param array|Number $value * * @return array * @@ -5551,30 +7405,55 @@ class Compiler public function assertList($value) { if ($value[0] !== Type::T_LIST) { - $this->throwError('expecting list, %s received', $value[0]); + throw $this->error('expecting list, %s received', $value[0]); } + assert(\is_array($value)); return $value; } + /** + * Gets the keywords of an argument list. + * + * Keys in the returned array are normalized names (underscores are replaced with dashes) + * without the leading `$`. + * Calling this helper with anything that an argument list received for a rest argument + * of the function argument declaration is not supported. + * + * @param array|Number $value + * + * @return array + */ + public function getArgumentListKeywords($value) + { + if ($value[0] !== Type::T_LIST || !isset($value[3]) || !\is_array($value[3])) { + throw new \InvalidArgumentException('The argument is not a sass argument list.'); + } + + return $value[3]; + } + /** * Assert value is a color * * @api * - * @param array $value + * @param array|Number $value + * @param string|null $varName * * @return array * - * @throws \Exception + * @throws SassScriptException */ - public function assertColor($value) + public function assertColor($value, $varName = null) { if ($color = $this->coerceColor($value)) { return $color; } - $this->throwError('expecting color, %s received', $value[0]); + $value = $this->compileValue($value); + + throw SassScriptException::forArgument("$value is not a color.", $varName); } /** @@ -5582,21 +7461,64 @@ class Compiler * * @api * - * @param array $value + * @param array|Number $value + * @param string|null $varName * - * @return integer|float + * @return Number * - * @throws \Exception + * @throws SassScriptException */ - public function assertNumber($value) + public function assertNumber($value, $varName = null) { - if ($value[0] !== Type::T_NUMBER) { - $this->throwError('expecting number, %s received', $value[0]); + if (!$value instanceof Number) { + $value = $this->compileValue($value); + throw SassScriptException::forArgument("$value is not a number.", $varName); } - return $value[1]; + return $value; } + /** + * Assert value is a integer + * + * @api + * + * @param array|Number $value + * @param string|null $varName + * + * @return int + * + * @throws SassScriptException + */ + public function assertInteger($value, $varName = null) + { + $value = $this->assertNumber($value, $varName)->getDimension(); + if (round($value - \intval($value), Number::PRECISION) > 0) { + throw SassScriptException::forArgument("$value is not an integer.", $varName); + } + + return intval($value); + } + + /** + * Extract the ... / alpha on the last argument of channel arg + * in color functions + * + * @param array $args + * @return array + */ + private function extractSlashAlphaInColorFunction($args) + { + $last = end($args); + if (\count($args) === 3 && $last[0] === Type::T_EXPRESSION && $last[1] === '/') { + array_pop($args); + $args[] = $last[2]; + $args[] = $last[3]; + } + return $args; + } + + /** * Make sure a color's components don't go out of bounds * @@ -5614,6 +7536,10 @@ class Compiler if ($c[$i] > 255) { $c[$i] = 255; } + + if (!\is_int($c[$i])) { + $c[$i] = round($c[$i]); + } } return $c; @@ -5622,11 +7548,11 @@ class Compiler /** * Convert RGB to HSL * - * @api + * @internal * - * @param integer $red - * @param integer $green - * @param integer $blue + * @param int $red + * @param int $green + * @param int $blue * * @return array */ @@ -5651,12 +7577,12 @@ class Compiler $h = 60 * ($green - $blue) / $d; } elseif ($green == $max) { $h = 60 * ($blue - $red) / $d + 120; - } elseif ($blue == $max) { + } else { $h = 60 * ($red - $green) / $d + 240; } } - return [Type::T_HSL, fmod($h, 360), $s * 100, $l / 5.1]; + return [Type::T_HSL, fmod($h + 360, 360), $s * 100, $l / 5.1]; } /** @@ -5685,7 +7611,7 @@ class Compiler } if ($h * 3 < 2) { - return $m1 + ($m2 - $m1) * (2/3 - $h) * 6; + return $m1 + ($m2 - $m1) * (2 / 3 - $h) * 6; } return $m1; @@ -5694,11 +7620,11 @@ class Compiler /** * Convert HSL to RGB * - * @api + * @internal * - * @param integer $hue H from 0 to 360 - * @param integer $saturation S from 0 to 100 - * @param integer $lightness L from 0 to 100 + * @param int|float $hue H from 0 to 360 + * @param int|float $saturation S from 0 to 100 + * @param int|float $lightness L from 0 to 100 * * @return array */ @@ -5715,35 +7641,133 @@ class Compiler $m2 = $l <= 0.5 ? $l * ($s + 1) : $l + $s - $l * $s; $m1 = $l * 2 - $m2; - $r = $this->hueToRGB($m1, $m2, $h + 1/3) * 255; + $r = $this->hueToRGB($m1, $m2, $h + 1 / 3) * 255; $g = $this->hueToRGB($m1, $m2, $h) * 255; - $b = $this->hueToRGB($m1, $m2, $h - 1/3) * 255; + $b = $this->hueToRGB($m1, $m2, $h - 1 / 3) * 255; $out = [Type::T_COLOR, $r, $g, $b]; return $out; } - // Built in functions - - protected static $libCall = ['name', 'args...']; - protected function libCall($args, $kwargs) + /** + * Convert HWB to RGB + * https://www.w3.org/TR/css-color-4/#hwb-to-rgb + * + * @api + * + * @param int|float $hue H from 0 to 360 + * @param int|float $whiteness W from 0 to 100 + * @param int|float $blackness B from 0 to 100 + * + * @return array + */ + private function HWBtoRGB($hue, $whiteness, $blackness) { - $name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true))); - $callArgs = []; + $w = min(100, max(0, $whiteness)) / 100; + $b = min(100, max(0, $blackness)) / 100; - // $kwargs['args'] is [Type::T_LIST, ',', [..]] - foreach ($kwargs['args'][2] as $varname => $arg) { - if (is_numeric($varname)) { - $varname = null; - } else { - $varname = [ 'var', $varname]; - } + $sum = $w + $b; + if ($sum > 1.0) { + $w = $w / $sum; + $b = $b / $sum; + } + $b = min(1.0 - $w, $b); - $callArgs[] = [$varname, $arg, false]; + $rgb = $this->toRGB($hue, 100, 50); + for($i = 1; $i < 4; $i++) { + $rgb[$i] *= (1.0 - $w - $b); + $rgb[$i] = round($rgb[$i] + 255 * $w + 0.0001); } - return $this->reduce([Type::T_FUNCTION_CALL, $name, $callArgs]); + return $rgb; + } + + /** + * Convert RGB to HWB + * + * @api + * + * @param int $red + * @param int $green + * @param int $blue + * + * @return array + */ + private function RGBtoHWB($red, $green, $blue) + { + $min = min($red, $green, $blue); + $max = max($red, $green, $blue); + + $d = $max - $min; + + if ((int) $d === 0) { + $h = 0; + } else { + + if ($red == $max) { + $h = 60 * ($green - $blue) / $d; + } elseif ($green == $max) { + $h = 60 * ($blue - $red) / $d + 120; + } else { + $h = 60 * ($red - $green) / $d + 240; + } + } + + return [Type::T_HWB, fmod($h, 360), $min / 255 * 100, 100 - $max / 255 *100]; + } + + + // Built in functions + + protected static $libCall = ['function', 'args...']; + protected function libCall($args) + { + $functionReference = $args[0]; + + if (in_array($functionReference[0], [Type::T_STRING, Type::T_KEYWORD])) { + $name = $this->compileStringContent($this->coerceString($functionReference)); + $warning = "Passing a string to call() is deprecated and will be illegal\n" + . "in Sass 4.0. Use call(function-reference($name)) instead."; + Warn::deprecation($warning); + $functionReference = $this->libGetFunction([$this->assertString($functionReference, 'function')]); + } + + if ($functionReference === static::$null) { + return static::$null; + } + + if (! in_array($functionReference[0], [Type::T_FUNCTION_REFERENCE, Type::T_FUNCTION])) { + throw $this->error('Function reference expected, got ' . $functionReference[0]); + } + + $callArgs = [ + [null, $args[1], true] + ]; + + return $this->reduce([Type::T_FUNCTION_CALL, $functionReference, $callArgs]); + } + + + protected static $libGetFunction = [ + ['name'], + ['name', 'css'] + ]; + protected function libGetFunction($args) + { + $name = $this->compileStringContent($this->assertString(array_shift($args), 'name')); + $isCss = false; + + if (count($args)) { + $isCss = array_shift($args); + $isCss = (($isCss === static::$true) ? true : false); + } + + if ($isCss) { + return [Type::T_FUNCTION, $name, [Type::T_LIST, ',', []]]; + } + + return $this->getFunctionReference($name, true); } protected static $libIf = ['condition', 'if-true', 'if-false:']; @@ -5763,11 +7787,8 @@ class Compiler { list($list, $value) = $args; - if ($value[0] === Type::T_MAP) { - return static::$null; - } - - if ($list[0] === Type::T_MAP || + if ( + $list[0] === Type::T_MAP || $list[0] === Type::T_STRING || $list[0] === Type::T_KEYWORD || $list[0] === Type::T_INTERPOLATE @@ -5779,6 +7800,22 @@ class Compiler return static::$null; } + // Numbers are represented with value objects, for which the PHP equality operator does not + // match the Sass rules (and we cannot overload it). As they are the only type of values + // represented with a value object for now, they require a special case. + if ($value instanceof Number) { + $key = 0; + foreach ($list[2] as $item) { + $key++; + $itemValue = $this->normalizeValue($item); + + if ($itemValue instanceof Number && $value->equals($itemValue)) { + return new Number($key, ''); + } + } + return static::$null; + } + $values = []; foreach ($list[2] as $item) { @@ -5787,7 +7824,7 @@ class Compiler $key = array_search($this->normalizeValue($value), $values); - return false === $key ? static::$null : $key + 1; + return false === $key ? static::$null : new Number($key + 1, ''); } protected static $libRgb = [ @@ -5796,9 +7833,17 @@ class Compiler ['channels'], ['red', 'green', 'blue'], ['red', 'green', 'blue', 'alpha'] ]; + + /** + * @param array $args + * @param array $kwargs + * @param string $funcName + * + * @return array + */ protected function libRgb($args, $kwargs, $funcName = 'rgb') { - switch (count($args)) { + switch (\count($args)) { case 1: if (! $color = $this->coerceColor($args[0], true)) { $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ')']]; @@ -5809,7 +7854,7 @@ class Compiler $color = [Type::T_COLOR, $args[0], $args[1], $args[2]]; if (! $color = $this->coerceColor($color)) { - $color = [Type::T_STRING, '', [$funcName .'(', $args[0], ', ', $args[1], ', ', $args[2], ')']]; + $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ')']]; } return $color; @@ -5825,7 +7870,7 @@ class Compiler [$funcName . '(', $color[1], ', ', $color[2], ', ', $color[3], ', ', $alpha, ')']]; } } else { - $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ')']]; + $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ')']]; } break; @@ -5854,33 +7899,126 @@ class Compiler return $this->libRgb($args, $kwargs, 'rgba'); } - // helper function for adjust_color, change_color, and scale_color - protected function alterColor($args, $fn) + /** + * Helper function for adjust_color, change_color, and scale_color + * + * @param array $args + * @param string $operation + * @param callable $fn + * + * @return array + * + * @phpstan-param callable(float|int, float|int|null, float|int): (float|int) $fn + */ + protected function alterColor(array $args, $operation, $fn) { - $color = $this->assertColor($args[0]); + $color = $this->assertColor($args[0], 'color'); - foreach ([1 => 1, 2 => 2, 3 => 3, 7 => 4] as $iarg => $irgba) { - if (isset($args[$iarg])) { - $val = $this->assertNumber($args[$iarg]); - - if (! isset($color[$irgba])) { - $color[$irgba] = (($irgba < 4) ? 0 : 1); - } - - $color[$irgba] = call_user_func($fn, $color[$irgba], $val, $iarg); - } + if ($args[1][2]) { + throw new SassScriptException('Only one positional argument is allowed. All other arguments must be passed by name.'); } - if (! empty($args[4]) || ! empty($args[5]) || ! empty($args[6])) { - $hsl = $this->toHSL($color[1], $color[2], $color[3]); + $kwargs = $this->getArgumentListKeywords($args[1]); - foreach ([4 => 1, 5 => 2, 6 => 3] as $iarg => $ihsl) { - if (! empty($args[$iarg])) { - $val = $this->assertNumber($args[$iarg]); - $hsl[$ihsl] = call_user_func($fn, $hsl[$ihsl], $val, $iarg); + $scale = $operation === 'scale'; + $change = $operation === 'change'; + + /** @phpstan-var callable(string, float|int, bool=, bool=): (float|int|null) $getParam */ + $getParam = function ($name, $max, $checkPercent = false, $assertPercent = false) use (&$kwargs, $scale, $change) { + if (!isset($kwargs[$name])) { + return null; + } + + $number = $this->assertNumber($kwargs[$name], $name); + unset($kwargs[$name]); + + if (!$scale && $checkPercent) { + if (!$number->hasUnit('%')) { + $warning = $this->error("{$name} Passing a number `$number` without unit % is deprecated."); + $this->logger->warn($warning->getMessage(), true); } } + if ($scale || $assertPercent) { + $number->assertUnit('%', $name); + } + + if ($scale) { + $max = 100; + } + + return $number->valueInRange($change ? 0 : -$max, $max, $name); + }; + + $alpha = $getParam('alpha', 1); + $red = $getParam('red', 255); + $green = $getParam('green', 255); + $blue = $getParam('blue', 255); + + if ($scale || !isset($kwargs['hue'])) { + $hue = null; + } else { + $hueNumber = $this->assertNumber($kwargs['hue'], 'hue'); + unset($kwargs['hue']); + $hue = $hueNumber->getDimension(); + } + $saturation = $getParam('saturation', 100, true); + $lightness = $getParam('lightness', 100, true); + $whiteness = $getParam('whiteness', 100, false, true); + $blackness = $getParam('blackness', 100, false, true); + + if (!empty($kwargs)) { + $unknownNames = array_keys($kwargs); + $lastName = array_pop($unknownNames); + $message = sprintf( + 'No argument%s named $%s%s.', + $unknownNames ? 's' : '', + $unknownNames ? implode(', $', $unknownNames) . ' or $' : '', + $lastName + ); + throw new SassScriptException($message); + } + + $hasRgb = $red !== null || $green !== null || $blue !== null; + $hasSL = $saturation !== null || $lightness !== null; + $hasWB = $whiteness !== null || $blackness !== null; + + if ($hasRgb && ($hasSL || $hasWB || $hue !== null)) { + throw new SassScriptException(sprintf('RGB parameters may not be passed along with %s parameters.', $hasWB ? 'HWB' : 'HSL')); + } + + if ($hasWB && $hasSL) { + throw new SassScriptException('HSL parameters may not be passed along with HWB parameters.'); + } + + if ($hasRgb) { + $color[1] = round($fn($color[1], $red, 255)); + $color[2] = round($fn($color[2], $green, 255)); + $color[3] = round($fn($color[3], $blue, 255)); + } elseif ($hasWB) { + $hwb = $this->RGBtoHWB($color[1], $color[2], $color[3]); + if ($hue !== null) { + $hwb[1] = $change ? $hue : $hwb[1] + $hue; + } + $hwb[2] = $fn($hwb[2], $whiteness, 100); + $hwb[3] = $fn($hwb[3], $blackness, 100); + + $rgb = $this->HWBtoRGB($hwb[1], $hwb[2], $hwb[3]); + + if (isset($color[4])) { + $rgb[4] = $color[4]; + } + + $color = $rgb; + } elseif ($hue !== null || $hasSL) { + $hsl = $this->toHSL($color[1], $color[2], $color[3]); + + if ($hue !== null) { + $hsl[1] = $change ? $hue : $hsl[1] + $hue; + } + $hsl[2] = $fn($hsl[2], $saturation, 100); + $hsl[3] = $fn($hsl[3], $lightness, 100); + $rgb = $this->toRGB($hsl[1], $hsl[2], $hsl[3]); if (isset($color[4])) { @@ -5890,58 +8028,54 @@ class Compiler $color = $rgb; } + if ($alpha !== null) { + $existingAlpha = isset($color[4]) ? $color[4] : 1; + $color[4] = $fn($existingAlpha, $alpha, 1); + } + return $color; } - protected static $libAdjustColor = [ - 'color', 'red:null', 'green:null', 'blue:null', - 'hue:null', 'saturation:null', 'lightness:null', 'alpha:null' - ]; + protected static $libAdjustColor = ['color', 'kwargs...']; protected function libAdjustColor($args) { - return $this->alterColor($args, function ($base, $alter, $i) { - return $base + $alter; + return $this->alterColor($args, 'adjust', function ($base, $alter, $max) { + if ($alter === null) { + return $base; + } + + $new = $base + $alter; + + if ($new < 0) { + return 0; + } + + if ($new > $max) { + return $max; + } + + return $new; }); } - protected static $libChangeColor = [ - 'color', 'red:null', 'green:null', 'blue:null', - 'hue:null', 'saturation:null', 'lightness:null', 'alpha:null' - ]; + protected static $libChangeColor = ['color', 'kwargs...']; protected function libChangeColor($args) { - return $this->alterColor($args, function ($base, $alter, $i) { + return $this->alterColor($args,'change', function ($base, $alter, $max) { + if ($alter === null) { + return $base; + } + return $alter; }); } - protected static $libScaleColor = [ - 'color', 'red:null', 'green:null', 'blue:null', - 'hue:null', 'saturation:null', 'lightness:null', 'alpha:null' - ]; + protected static $libScaleColor = ['color', 'kwargs...']; protected function libScaleColor($args) { - return $this->alterColor($args, function ($base, $scale, $i) { - // 1, 2, 3 - rgb - // 4, 5, 6 - hsl - // 7 - a - switch ($i) { - case 1: - case 2: - case 3: - $max = 255; - break; - - case 4: - $max = 360; - break; - - case 7: - $max = 1; - break; - - default: - $max = 100; + return $this->alterColor($args, 'scale', function ($base, $scale, $max) { + if ($scale === null) { + return $base; } $scale = $scale / 100; @@ -5958,6 +8092,11 @@ class Compiler protected function libIeHexStr($args) { $color = $this->coerceColor($args[0]); + + if (\is_null($color)) { + throw $this->error('Error: argument `$color` of `ie-hex-str($color)` must be a color'); + } + $color[4] = isset($color[4]) ? round(255 * $color[4]) : 255; return [Type::T_STRING, '', [sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3])]]; @@ -5968,7 +8107,11 @@ class Compiler { $color = $this->coerceColor($args[0]); - return $color[1]; + if (\is_null($color)) { + throw $this->error('Error: argument `$color` of `red($color)` must be a color'); + } + + return new Number((int) $color[1], ''); } protected static $libGreen = ['color']; @@ -5976,7 +8119,11 @@ class Compiler { $color = $this->coerceColor($args[0]); - return $color[2]; + if (\is_null($color)) { + throw $this->error('Error: argument `$color` of `green($color)` must be a color'); + } + + return new Number((int) $color[2], ''); } protected static $libBlue = ['color']; @@ -5984,14 +8131,18 @@ class Compiler { $color = $this->coerceColor($args[0]); - return $color[3]; + if (\is_null($color)) { + throw $this->error('Error: argument `$color` of `blue($color)` must be a color'); + } + + return new Number((int) $color[3], ''); } protected static $libAlpha = ['color']; protected function libAlpha($args) { if ($color = $this->coerceColor($args[0])) { - return isset($color[4]) ? $color[4] : 1; + return new Number(isset($color[4]) ? $color[4] : 1, ''); } // this might be the IE function, so return value unchanged @@ -6003,7 +8154,7 @@ class Compiler { $value = $args[0]; - if ($value[0] === Type::T_NUMBER) { + if ($value instanceof Number) { return null; } @@ -6011,78 +8162,129 @@ class Compiler } // mix two colors - protected static $libMix = ['color-1', 'color-2', 'weight:0.5']; + protected static $libMix = [ + ['color1', 'color2', 'weight:50%'], + ['color-1', 'color-2', 'weight:50%'] + ]; protected function libMix($args) { list($first, $second, $weight) = $args; - $first = $this->assertColor($first); - $second = $this->assertColor($second); - - if (! isset($weight)) { - $weight = 0.5; - } else { - $weight = $this->coercePercent($weight); - } + $first = $this->assertColor($first, 'color1'); + $second = $this->assertColor($second, 'color2'); + $weightScale = $this->assertNumber($weight, 'weight')->valueInRange(0, 100, 'weight') / 100; $firstAlpha = isset($first[4]) ? $first[4] : 1; $secondAlpha = isset($second[4]) ? $second[4] : 1; - $w = $weight * 2 - 1; - $a = $firstAlpha - $secondAlpha; + $normalizedWeight = $weightScale * 2 - 1; + $alphaDistance = $firstAlpha - $secondAlpha; - $w1 = (($w * $a === -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2.0; - $w2 = 1.0 - $w1; + $combinedWeight = $normalizedWeight * $alphaDistance == -1 ? $normalizedWeight : ($normalizedWeight + $alphaDistance) / (1 + $normalizedWeight * $alphaDistance); + $weight1 = ($combinedWeight + 1) / 2.0; + $weight2 = 1.0 - $weight1; $new = [Type::T_COLOR, - $w1 * $first[1] + $w2 * $second[1], - $w1 * $first[2] + $w2 * $second[2], - $w1 * $first[3] + $w2 * $second[3], + $weight1 * $first[1] + $weight2 * $second[1], + $weight1 * $first[2] + $weight2 * $second[2], + $weight1 * $first[3] + $weight2 * $second[3], ]; if ($firstAlpha != 1.0 || $secondAlpha != 1.0) { - $new[] = $firstAlpha * $weight + $secondAlpha * (1 - $weight); + $new[] = $firstAlpha * $weightScale + $secondAlpha * (1 - $weightScale); } return $this->fixColor($new); } - protected static $libHsl =[ + protected static $libHsl = [ ['channels'], + ['hue', 'saturation'], ['hue', 'saturation', 'lightness'], ['hue', 'saturation', 'lightness', 'alpha'] ]; + + /** + * @param array $args + * @param array $kwargs + * @param string $funcName + * + * @return array|null + */ protected function libHsl($args, $kwargs, $funcName = 'hsl') { - if (count($args) == 1) { - if ($args[0][0] !== Type::T_LIST || count($args[0][2]) < 3 || count($args[0][2]) > 4) { + $args_to_check = $args; + + if (\count($args) == 1) { + if ($args[0][0] !== Type::T_LIST || \count($args[0][2]) < 3 || \count($args[0][2]) > 4) { return [Type::T_STRING, '', [$funcName . '(', $args[0], ')']]; } $args = $args[0][2]; + $args_to_check = $kwargs['channels'][2]; } - $hue = $this->compileColorPartValue($args[0], 0, 360, false, false, true); - $saturation = $this->compileColorPartValue($args[1], 0, 100, false); - $lightness = $this->compileColorPartValue($args[2], 0, 100, false); + if (\count($args) === 2) { + // if var() is used as an argument, return as a css function + foreach ($args as $arg) { + if ($arg[0] === Type::T_FUNCTION && in_array($arg[1], ['var'])) { + return null; + } + } + throw new SassScriptException('Missing argument $lightness.'); + } + + foreach ($kwargs as $arg) { + if (in_array($arg[0], [Type::T_FUNCTION_CALL, Type::T_FUNCTION]) && in_array($arg[1], ['min', 'max'])) { + return null; + } + } + + foreach ($args_to_check as $k => $arg) { + if (in_array($arg[0], [Type::T_FUNCTION_CALL, Type::T_FUNCTION]) && in_array($arg[1], ['min', 'max'])) { + if (count($kwargs) > 1 || ($k >= 2 && count($args) === 4)) { + return null; + } + + $args[$k] = $this->stringifyFncallArgs($arg); + } + + if ( + $k >= 2 && count($args) === 4 && + in_array($arg[0], [Type::T_FUNCTION_CALL, Type::T_FUNCTION]) && + in_array($arg[1], ['calc','env']) + ) { + return null; + } + } + + $hue = $this->reduce($args[0]); + $saturation = $this->reduce($args[1]); + $lightness = $this->reduce($args[2]); $alpha = null; - if (count($args) === 4) { + if (\count($args) === 4) { $alpha = $this->compileColorPartValue($args[3], 0, 100, false); - if (! is_numeric($hue) || ! is_numeric($saturation) || ! is_numeric($lightness) || ! is_numeric($alpha)) { + if (!$hue instanceof Number || !$saturation instanceof Number || ! $lightness instanceof Number || ! is_numeric($alpha)) { return [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ', ', $args[3], ')']]; } } else { - if (! is_numeric($hue) || ! is_numeric($saturation) || ! is_numeric($lightness)) { + if (!$hue instanceof Number || !$saturation instanceof Number || ! $lightness instanceof Number) { return [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ')']]; } } - $color = $this->toRGB($hue, $saturation, $lightness); + $hueValue = fmod($hue->getDimension(), 360); - if (! is_null($alpha)) { + while ($hueValue < 0) { + $hueValue += 360; + } + + $color = $this->toRGB($hueValue, max(0, min($saturation->getDimension(), 100)), max(0, min($lightness->getDimension(), 100))); + + if (! \is_null($alpha)) { $color[4] = $alpha; } @@ -6091,7 +8293,9 @@ class Compiler protected static $libHsla = [ ['channels'], - ['hue', 'saturation', 'lightness', 'alpha:1'] ]; + ['hue', 'saturation'], + ['hue', 'saturation', 'lightness'], + ['hue', 'saturation', 'lightness', 'alpha']]; protected function libHsla($args, $kwargs) { return $this->libHsl($args, $kwargs, 'hsla'); @@ -6100,34 +8304,173 @@ class Compiler protected static $libHue = ['color']; protected function libHue($args) { - $color = $this->assertColor($args[0]); + $color = $this->assertColor($args[0], 'color'); $hsl = $this->toHSL($color[1], $color[2], $color[3]); - return new Node\Number($hsl[1], 'deg'); + return new Number($hsl[1], 'deg'); } protected static $libSaturation = ['color']; protected function libSaturation($args) { - $color = $this->assertColor($args[0]); + $color = $this->assertColor($args[0], 'color'); $hsl = $this->toHSL($color[1], $color[2], $color[3]); - return new Node\Number($hsl[2], '%'); + return new Number($hsl[2], '%'); } protected static $libLightness = ['color']; protected function libLightness($args) { - $color = $this->assertColor($args[0]); + $color = $this->assertColor($args[0], 'color'); $hsl = $this->toHSL($color[1], $color[2], $color[3]); - return new Node\Number($hsl[3], '%'); + return new Number($hsl[3], '%'); } + /* + * Todo : a integrer dans le futur module color + protected static $libHwb = [ + ['channels'], + ['hue', 'whiteness', 'blackness'], + ['hue', 'whiteness', 'blackness', 'alpha'] ]; + protected function libHwb($args, $kwargs, $funcName = 'hwb') + { + $args_to_check = $args; + + if (\count($args) == 1) { + if ($args[0][0] !== Type::T_LIST) { + throw $this->error("Missing elements \$whiteness and \$blackness"); + } + + if (\trim($args[0][1])) { + throw $this->error("\$channels must be a space-separated list."); + } + + if (! empty($args[0]['enclosing'])) { + throw $this->error("\$channels must be an unbracketed list."); + } + + $args = $args[0][2]; + if (\count($args) > 3) { + throw $this->error("hwb() : Only 3 elements are allowed but ". \count($args) . "were passed"); + } + + $args_to_check = $this->extractSlashAlphaInColorFunction($kwargs['channels'][2]); + if (\count($args_to_check) !== \count($kwargs['channels'][2])) { + $args = $args_to_check; + } + } + + if (\count($args_to_check) < 2) { + throw $this->error("Missing elements \$whiteness and \$blackness"); + } + if (\count($args_to_check) < 3) { + throw $this->error("Missing element \$blackness"); + } + if (\count($args_to_check) > 4) { + throw $this->error("hwb() : Only 4 elements are allowed but ". \count($args) . "were passed"); + } + + foreach ($kwargs as $k => $arg) { + if (in_array($arg[0], [Type::T_FUNCTION_CALL]) && in_array($arg[1], ['min', 'max'])) { + return null; + } + } + + foreach ($args_to_check as $k => $arg) { + if (in_array($arg[0], [Type::T_FUNCTION_CALL]) && in_array($arg[1], ['min', 'max'])) { + if (count($kwargs) > 1 || ($k >= 2 && count($args) === 4)) { + return null; + } + + $args[$k] = $this->stringifyFncallArgs($arg); + } + + if ( + $k >= 2 && count($args) === 4 && + in_array($arg[0], [Type::T_FUNCTION_CALL, Type::T_FUNCTION]) && + in_array($arg[1], ['calc','env']) + ) { + return null; + } + } + + $hue = $this->reduce($args[0]); + $whiteness = $this->reduce($args[1]); + $blackness = $this->reduce($args[2]); + $alpha = null; + + if (\count($args) === 4) { + $alpha = $this->compileColorPartValue($args[3], 0, 1, false); + + if (! \is_numeric($alpha)) { + $val = $this->compileValue($args[3]); + throw $this->error("\$alpha: $val is not a number"); + } + } + + $this->assertNumber($hue, 'hue'); + $this->assertUnit($whiteness, ['%'], 'whiteness'); + $this->assertUnit($blackness, ['%'], 'blackness'); + + $this->assertRange($whiteness, 0, 100, "0% and 100%", "whiteness"); + $this->assertRange($blackness, 0, 100, "0% and 100%", "blackness"); + + $w = $whiteness->getDimension(); + $b = $blackness->getDimension(); + + $hueValue = $hue->getDimension() % 360; + + while ($hueValue < 0) { + $hueValue += 360; + } + + $color = $this->HWBtoRGB($hueValue, $w, $b); + + if (! \is_null($alpha)) { + $color[4] = $alpha; + } + + return $color; + } + + protected static $libWhiteness = ['color']; + protected function libWhiteness($args, $kwargs, $funcName = 'whiteness') { + + $color = $this->assertColor($args[0]); + $hwb = $this->RGBtoHWB($color[1], $color[2], $color[3]); + + return new Number($hwb[2], '%'); + } + + protected static $libBlackness = ['color']; + protected function libBlackness($args, $kwargs, $funcName = 'blackness') { + + $color = $this->assertColor($args[0]); + $hwb = $this->RGBtoHWB($color[1], $color[2], $color[3]); + + return new Number($hwb[3], '%'); + } + */ + + /** + * @param array $color + * @param int $idx + * @param int|float $amount + * + * @return array + */ protected function adjustHsl($color, $idx, $amount) { $hsl = $this->toHSL($color[1], $color[2], $color[3]); $hsl[$idx] += $amount; + + if ($idx !== 1) { + // Clamp the saturation and lightness + $hsl[$idx] = min(max(0, $hsl[$idx]), 100); + } + $out = $this->toRGB($hsl[1], $hsl[2], $hsl[3]); if (isset($color[4])) { @@ -6140,8 +8483,8 @@ class Compiler protected static $libAdjustHue = ['color', 'degrees']; protected function libAdjustHue($args) { - $color = $this->assertColor($args[0]); - $degrees = $this->assertNumber($args[1]); + $color = $this->assertColor($args[0], 'color'); + $degrees = $this->assertNumber($args[1], 'degrees')->getDimension(); return $this->adjustHsl($color, 1, $degrees); } @@ -6149,7 +8492,7 @@ class Compiler protected static $libLighten = ['color', 'amount']; protected function libLighten($args) { - $color = $this->assertColor($args[0]); + $color = $this->assertColor($args[0], 'color'); $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%'); return $this->adjustHsl($color, 3, $amount); @@ -6158,34 +8501,36 @@ class Compiler protected static $libDarken = ['color', 'amount']; protected function libDarken($args) { - $color = $this->assertColor($args[0]); + $color = $this->assertColor($args[0], 'color'); $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%'); return $this->adjustHsl($color, 3, -$amount); } - protected static $libSaturate = [['color', 'amount'], ['number']]; + protected static $libSaturate = [['color', 'amount'], ['amount']]; protected function libSaturate($args) { $value = $args[0]; - if ($value[0] === Type::T_NUMBER) { + if (count($args) === 1) { + $this->assertNumber($args[0], 'amount'); + return null; } - $color = $this->assertColor($value); - $amount = 100 * $this->coercePercent($args[1]); + $color = $this->assertColor($args[0], 'color'); + $amount = $this->assertNumber($args[1], 'amount'); - return $this->adjustHsl($color, 2, $amount); + return $this->adjustHsl($color, 2, $amount->valueInRange(0, 100, 'amount')); } protected static $libDesaturate = ['color', 'amount']; protected function libDesaturate($args) { - $color = $this->assertColor($args[0]); - $amount = 100 * $this->coercePercent($args[1]); + $color = $this->assertColor($args[0], 'color'); + $amount = $this->assertNumber($args[1], 'amount'); - return $this->adjustHsl($color, 2, -$amount); + return $this->adjustHsl($color, 2, -$amount->valueInRange(0, 100, 'amount')); } protected static $libGrayscale = ['color']; @@ -6193,55 +8538,51 @@ class Compiler { $value = $args[0]; - if ($value[0] === Type::T_NUMBER) { + if ($value instanceof Number) { return null; } - return $this->adjustHsl($this->assertColor($value), 2, -100); + return $this->adjustHsl($this->assertColor($value, 'color'), 2, -100); } protected static $libComplement = ['color']; protected function libComplement($args) { - return $this->adjustHsl($this->assertColor($args[0]), 1, 180); + return $this->adjustHsl($this->assertColor($args[0], 'color'), 1, 180); } - protected static $libInvert = ['color', 'weight:1']; + protected static $libInvert = ['color', 'weight:100%']; protected function libInvert($args) { - list($value, $weight) = $args; + $value = $args[0]; - if (! isset($weight)) { - $weight = 1; - } else { - $weight = $this->coercePercent($weight); - } + $weight = $this->assertNumber($args[1], 'weight'); + + if ($value instanceof Number) { + if ($weight->getDimension() != 100 || !$weight->hasUnit('%')) { + throw new SassScriptException('Only one argument may be passed to the plain-CSS invert() function.'); + } - if ($value[0] === Type::T_NUMBER) { return null; } - $color = $this->assertColor($value); + $color = $this->assertColor($value, 'color'); $inverted = $color; $inverted[1] = 255 - $inverted[1]; $inverted[2] = 255 - $inverted[2]; $inverted[3] = 255 - $inverted[3]; - if ($weight < 1) { - return $this->libMix([$inverted, $color, [Type::T_NUMBER, $weight]]); - } - - return $inverted; + return $this->libMix([$inverted, $color, $weight]); } // increases opacity by amount protected static $libOpacify = ['color', 'amount']; protected function libOpacify($args) { - $color = $this->assertColor($args[0]); - $amount = $this->coercePercent($args[1]); + $color = $this->assertColor($args[0], 'color'); + $amount = $this->assertNumber($args[1], 'amount'); - $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount; + $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount->valueInRange(0, 1, 'amount'); $color[4] = min(1, max(0, $color[4])); return $color; @@ -6257,10 +8598,10 @@ class Compiler protected static $libTransparentize = ['color', 'amount']; protected function libTransparentize($args) { - $color = $this->assertColor($args[0]); - $amount = $this->coercePercent($args[1]); + $color = $this->assertColor($args[0], 'color'); + $amount = $this->assertNumber($args[1], 'amount'); - $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount; + $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount->valueInRange(0, 1, 'amount'); $color[4] = min(1, max(0, $color[4])); return $color; @@ -6275,166 +8616,165 @@ class Compiler protected static $libUnquote = ['string']; protected function libUnquote($args) { - $str = $args[0]; + try { + $str = $this->assertString($args[0], 'string'); + } catch (SassScriptException $e) { + $value = $this->compileValue($args[0]); + $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); + $line = $this->sourceLine; - if ($str[0] === Type::T_STRING) { - $str[1] = ''; + $message = "Passing $value, a non-string value, to unquote() +will be an error in future versions of Sass.\n on line $line of $fname"; + + $this->logger->warn($message, true); + + return $args[0]; } + $str[1] = ''; + return $str; } protected static $libQuote = ['string']; protected function libQuote($args) { - $value = $args[0]; + $value = $this->assertString($args[0], 'string'); - if ($value[0] === Type::T_STRING && ! empty($value[1])) { - return $value; - } + $value[1] = '"'; - return [Type::T_STRING, '"', [$value]]; + return $value; } - protected static $libPercentage = ['value']; + protected static $libPercentage = ['number']; protected function libPercentage($args) { - return new Node\Number($this->coercePercent($args[0]) * 100, '%'); + $num = $this->assertNumber($args[0], 'number'); + $num->assertNoUnits('number'); + + return new Number($num->getDimension() * 100, '%'); } - protected static $libRound = ['value']; + protected static $libRound = ['number']; protected function libRound($args) { - $num = $args[0]; + $num = $this->assertNumber($args[0], 'number'); - return new Node\Number(round($num[1]), $num[2]); + return new Number(round($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits()); } - protected static $libFloor = ['value']; + protected static $libFloor = ['number']; protected function libFloor($args) { - $num = $args[0]; + $num = $this->assertNumber($args[0], 'number'); - return new Node\Number(floor($num[1]), $num[2]); + return new Number(floor($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits()); } - protected static $libCeil = ['value']; + protected static $libCeil = ['number']; protected function libCeil($args) { - $num = $args[0]; + $num = $this->assertNumber($args[0], 'number'); - return new Node\Number(ceil($num[1]), $num[2]); + return new Number(ceil($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits()); } - protected static $libAbs = ['value']; + protected static $libAbs = ['number']; protected function libAbs($args) { - $num = $args[0]; + $num = $this->assertNumber($args[0], 'number'); - return new Node\Number(abs($num[1]), $num[2]); + return new Number(abs($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits()); } + protected static $libMin = ['numbers...']; protected function libMin($args) { - $numbers = $this->getNormalizedNumbers($args); + /** + * @var Number|null + */ $min = null; - foreach ($numbers as $key => $number) { - if (is_null($min) || $number[1] <= $min[1]) { - $min = [$key, $number[1]]; + foreach ($args[0][2] as $arg) { + $number = $this->assertNumber($arg); + + if (\is_null($min) || $min->greaterThan($number)) { + $min = $number; } } - return $args[$min[0]]; + if (!\is_null($min)) { + return $min; + } + + throw $this->error('At least one argument must be passed.'); } + protected static $libMax = ['numbers...']; protected function libMax($args) { - $numbers = $this->getNormalizedNumbers($args); + /** + * @var Number|null + */ $max = null; - foreach ($numbers as $key => $number) { - if (is_null($max) || $number[1] >= $max[1]) { - $max = [$key, $number[1]]; + foreach ($args[0][2] as $arg) { + $number = $this->assertNumber($arg); + + if (\is_null($max) || $max->lessThan($number)) { + $max = $number; } } - return $args[$max[0]]; - } - - /** - * Helper to normalize args containing numbers - * - * @param array $args - * - * @return array - */ - protected function getNormalizedNumbers($args) - { - $unit = null; - $originalUnit = null; - $numbers = []; - - foreach ($args as $key => $item) { - if ($item[0] !== Type::T_NUMBER) { - $this->throwError('%s is not a number', $item[0]); - break; - } - - $number = $item->normalize(); - - if (is_null($unit)) { - $unit = $number[2]; - $originalUnit = $item->unitStr(); - } elseif ($number[1] && $unit !== $number[2]) { - $this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item->unitStr()); - break; - } - - $numbers[$key] = $number; + if (!\is_null($max)) { + return $max; } - return $numbers; + throw $this->error('At least one argument must be passed.'); } protected static $libLength = ['list']; protected function libLength($args) { - $list = $this->coerceList($args[0]); + $list = $this->coerceList($args[0], ',', true); - return count($list[2]); + return new Number(\count($list[2]), ''); } - //protected static $libListSeparator = ['list...']; + protected static $libListSeparator = ['list']; protected function libListSeparator($args) { - if (count($args) > 1) { - return 'comma'; + if (! \in_array($args[0][0], [Type::T_LIST, Type::T_MAP])) { + return [Type::T_KEYWORD, 'space']; } $list = $this->coerceList($args[0]); - if (count($list[2]) <= 1) { - return 'space'; + if ($list[1] === '' && \count($list[2]) <= 1 && empty($list['enclosing'])) { + return [Type::T_KEYWORD, 'space']; } if ($list[1] === ',') { - return 'comma'; + return [Type::T_KEYWORD, 'comma']; } - return 'space'; + if ($list[1] === '/') { + return [Type::T_KEYWORD, 'slash']; + } + + return [Type::T_KEYWORD, 'space']; } protected static $libNth = ['list', 'n']; protected function libNth($args) { - $list = $this->coerceList($args[0]); - $n = $this->assertNumber($args[1]); + $list = $this->coerceList($args[0], ',', false); + $n = $this->assertNumber($args[1])->getDimension(); if ($n > 0) { $n--; } elseif ($n < 0) { - $n += count($list[2]); + $n += \count($list[2]); } return isset($list[2][$n]) ? $list[2][$n] : static::$defaultValue; @@ -6444,18 +8784,16 @@ class Compiler protected function libSetNth($args) { $list = $this->coerceList($args[0]); - $n = $this->assertNumber($args[1]); + $n = $this->assertNumber($args[1])->getDimension(); if ($n > 0) { $n--; } elseif ($n < 0) { - $n += count($list[2]); + $n += \count($list[2]); } if (! isset($list[2][$n])) { - $this->throwError('Invalid argument for "n"'); - - return null; + throw $this->error('Invalid argument for "n"'); } $list[2][$n] = $args[2]; @@ -6463,29 +8801,78 @@ class Compiler return $list; } - protected static $libMapGet = ['map', 'key']; + protected static $libMapGet = ['map', 'key', 'keys...']; protected function libMapGet($args) { - $map = $this->assertMap($args[0]); - $key = $args[1]; + $map = $this->assertMap($args[0], 'map'); + if (!isset($args[2])) { + // BC layer for usages of the function from PHP code rather than from the Sass function + $args[2] = self::$emptyArgumentList; + } + $keys = array_merge([$args[1]], $args[2][2]); + $value = static::$null; - if (! is_null($key)) { - $key = $this->compileStringContent($this->coerceString($key)); + foreach ($keys as $key) { + if (!\is_array($map) || $map[0] !== Type::T_MAP) { + return static::$null; + } - for ($i = count($map[1]) - 1; $i >= 0; $i--) { - if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) { - return $map[2][$i]; - } + $map = $this->mapGet($map, $key); + + if ($map === null) { + return static::$null; + } + + $value = $map; + } + + return $value; + } + + /** + * Gets the value corresponding to that key in the map + * + * @param array $map + * @param Number|array $key + * + * @return Number|array|null + */ + private function mapGet(array $map, $key) + { + $index = $this->mapGetEntryIndex($map, $key); + + if ($index !== null) { + return $map[2][$index]; + } + + return null; + } + + /** + * Gets the index corresponding to that key in the map entries + * + * @param array $map + * @param Number|array $key + * + * @return int|null + */ + private function mapGetEntryIndex(array $map, $key) + { + $key = $this->compileStringContent($this->coerceString($key)); + + for ($i = \count($map[1]) - 1; $i >= 0; $i--) { + if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) { + return $i; } } - return static::$null; + return null; } protected static $libMapKeys = ['map']; protected function libMapKeys($args) { - $map = $this->assertMap($args[0]); + $map = $this->assertMap($args[0], 'map'); $keys = $map[1]; return [Type::T_LIST, ',', $keys]; @@ -6494,20 +8881,33 @@ class Compiler protected static $libMapValues = ['map']; protected function libMapValues($args) { - $map = $this->assertMap($args[0]); + $map = $this->assertMap($args[0], 'map'); $values = $map[2]; return [Type::T_LIST, ',', $values]; } - protected static $libMapRemove = ['map', 'key']; + protected static $libMapRemove = [ + ['map'], + ['map', 'key', 'keys...'], + ]; protected function libMapRemove($args) { - $map = $this->assertMap($args[0]); - $key = $this->compileStringContent($this->coerceString($args[1])); + $map = $this->assertMap($args[0], 'map'); - for ($i = count($map[1]) - 1; $i >= 0; $i--) { - if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) { + if (\count($args) === 1) { + return $map; + } + + $keys = []; + $keys[] = $this->compileStringContent($this->coerceString($args[1])); + + foreach ($args[2][2] as $key) { + $keys[] = $this->compileStringContent($this->coerceString($key)); + } + + for ($i = \count($map[1]) - 1; $i >= 0; $i--) { + if (in_array($this->compileStringContent($this->coerceString($map[1][$i])), $keys)) { array_splice($map[1], $i, 1); array_splice($map[2], $i, 1); } @@ -6516,13 +8916,40 @@ class Compiler return $map; } - protected static $libMapHasKey = ['map', 'key']; + protected static $libMapHasKey = ['map', 'key', 'keys...']; protected function libMapHasKey($args) { - $map = $this->assertMap($args[0]); - $key = $this->compileStringContent($this->coerceString($args[1])); + $map = $this->assertMap($args[0], 'map'); + if (!isset($args[2])) { + // BC layer for usages of the function from PHP code rather than from the Sass function + $args[2] = self::$emptyArgumentList; + } + $keys = array_merge([$args[1]], $args[2][2]); + $lastKey = array_pop($keys); - for ($i = count($map[1]) - 1; $i >= 0; $i--) { + foreach ($keys as $key) { + $value = $this->mapGet($map, $key); + + if ($value === null || $value instanceof Number || $value[0] !== Type::T_MAP) { + return self::$false; + } + + $map = $value; + } + + return $this->toBool($this->mapHasKey($map, $lastKey)); + } + + /** + * @param array|Number $keyValue + * + * @return bool + */ + private function mapHasKey(array $map, $keyValue) + { + $key = $this->compileStringContent($this->coerceString($keyValue)); + + for ($i = \count($map[1]) - 1; $i >= 0; $i--) { if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) { return true; } @@ -6531,23 +8958,129 @@ class Compiler return false; } - protected static $libMapMerge = ['map-1', 'map-2']; + protected static $libMapMerge = [ + ['map1', 'map2'], + ['map-1', 'map-2'], + ['map1', 'args...'] + ]; protected function libMapMerge($args) { - $map1 = $this->assertMap($args[0]); - $map2 = $this->assertMap($args[1]); + $map1 = $this->assertMap($args[0], 'map1'); + $map2 = $args[1]; + $keys = []; + if ($map2[0] === Type::T_LIST && isset($map2[3]) && \is_array($map2[3])) { + // This is an argument list for the variadic signature + if (\count($map2[2]) === 0) { + throw new SassScriptException('Expected $args to contain a key.'); + } + if (\count($map2[2]) === 1) { + throw new SassScriptException('Expected $args to contain a value.'); + } + $keys = $map2[2]; + $map2 = array_pop($keys); + } + $map2 = $this->assertMap($map2, 'map2'); - foreach ($map2[1] as $i2 => $key2) { - $key = $this->compileStringContent($this->coerceString($key2)); + return $this->modifyMap($map1, $keys, function ($oldValue) use ($map2) { + $nestedMap = $this->tryMap($oldValue); - foreach ($map1[1] as $i1 => $key1) { - if ($key === $this->compileStringContent($this->coerceString($key1))) { - $map1[2][$i1] = $map2[2][$i2]; - continue 2; - } + if ($nestedMap === null) { + return $map2; } - $map1[1][] = $map2[1][$i2]; + return $this->mergeMaps($nestedMap, $map2); + }); + } + + /** + * @param array $map + * @param array $keys + * @param callable $modify + * @param bool $addNesting + * + * @return Number|array + * + * @phpstan-param array $keys + * @phpstan-param callable(Number|array): (Number|array) $modify + */ + private function modifyMap(array $map, array $keys, callable $modify, $addNesting = true) + { + if ($keys === []) { + return $modify($map); + } + + return $this->modifyNestedMap($map, $keys, $modify, $addNesting); + } + + /** + * @param array $map + * @param array $keys + * @param callable $modify + * @param bool $addNesting + * + * @return array + * + * @phpstan-param non-empty-array $keys + * @phpstan-param callable(Number|array): (Number|array) $modify + */ + private function modifyNestedMap(array $map, array $keys, callable $modify, $addNesting) + { + $key = array_shift($keys); + + $nestedValueIndex = $this->mapGetEntryIndex($map, $key); + + if ($keys === []) { + if ($nestedValueIndex !== null) { + $map[2][$nestedValueIndex] = $modify($map[2][$nestedValueIndex]); + } else { + $map[1][] = $key; + $map[2][] = $modify(self::$null); + } + + return $map; + } + + $nestedMap = $nestedValueIndex !== null ? $this->tryMap($map[2][$nestedValueIndex]) : null; + + if ($nestedMap === null && !$addNesting) { + return $map; + } + + if ($nestedMap === null) { + $nestedMap = self::$emptyMap; + } + + $newNestedMap = $this->modifyNestedMap($nestedMap, $keys, $modify, $addNesting); + + if ($nestedValueIndex !== null) { + $map[2][$nestedValueIndex] = $newNestedMap; + } else { + $map[1][] = $key; + $map[2][] = $newNestedMap; + } + + return $map; + } + + /** + * Merges 2 Sass maps together + * + * @param array $map1 + * @param array $map2 + * + * @return array + */ + private function mergeMaps(array $map1, array $map2) + { + foreach ($map2[1] as $i2 => $key2) { + $map1EntryIndex = $this->mapGetEntryIndex($map1, $key2); + + if ($map1EntryIndex !== null) { + $map1[2][$map1EntryIndex] = $map2[2][$i2]; + continue; + } + + $map1[1][] = $key2; $map1[2][] = $map2[2][$i2]; } @@ -6557,12 +9090,18 @@ class Compiler protected static $libKeywords = ['args']; protected function libKeywords($args) { - $this->assertList($args[0]); + $value = $args[0]; + + if ($value[0] !== Type::T_LIST || !isset($value[3]) || !\is_array($value[3])) { + $compiledValue = $this->compileValue($value); + + throw SassScriptException::forArgument($compiledValue . ' is not an argument list.', 'args'); + } $keys = []; $values = []; - foreach ($args[0][2] as $name => $arg) { + foreach ($this->getArgumentListKeywords($value) as $name => $arg) { $keys[] = [Type::T_KEYWORD, $name]; $values[] = $arg; } @@ -6575,15 +9114,27 @@ class Compiler { $list = $args[0]; $this->coerceList($list, ' '); + if (! empty($list['enclosing']) && $list['enclosing'] === 'bracket') { - return true; + return self::$true; } - return false; + + return self::$false; } - + /** + * @param array $list1 + * @param array|Number|null $sep + * + * @return string + * @throws CompilerException + * + * @deprecated + */ protected function listSeparatorForJoin($list1, $sep) { + @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); + if (! isset($sep)) { return $list1[1]; } @@ -6600,14 +9151,40 @@ class Compiler } } - protected static $libJoin = ['list1', 'list2', 'separator:null', 'bracketed:auto']; + protected static $libJoin = ['list1', 'list2', 'separator:auto', 'bracketed:auto']; protected function libJoin($args) { list($list1, $list2, $sep, $bracketed) = $args; - $list1 = $this->coerceList($list1, ' '); - $list2 = $this->coerceList($list2, ' '); - $sep = $this->listSeparatorForJoin($list1, $sep); + $list1 = $this->coerceList($list1, ' ', true); + $list2 = $this->coerceList($list2, ' ', true); + + switch ($this->compileStringContent($this->assertString($sep, 'separator'))) { + case 'comma': + $separator = ','; + break; + + case 'space': + $separator = ' '; + break; + + case 'slash': + $separator = '/'; + break; + + case 'auto': + if ($list1[1] !== '' || count($list1[2]) > 1 || !empty($list1['enclosing']) && $list1['enclosing'] !== 'parent') { + $separator = $list1[1] ?: ' '; + } elseif ($list2[1] !== '' || count($list2[2]) > 1 || !empty($list2['enclosing']) && $list2['enclosing'] !== 'parent') { + $separator = $list2[1] ?: ' '; + } else { + $separator = ' '; + } + break; + + default: + throw SassScriptException::forArgument('Must be "space", "comma", "slash", or "auto".', 'separator'); + } if ($bracketed === static::$true) { $bracketed = true; @@ -6620,6 +9197,7 @@ class Compiler } else { $bracketed = $this->compileValue($bracketed); $bracketed = ! ! $bracketed; + if ($bracketed === true) { $bracketed = true; } @@ -6627,60 +9205,91 @@ class Compiler if ($bracketed === 'auto') { $bracketed = false; + if (! empty($list1['enclosing']) && $list1['enclosing'] === 'bracket') { $bracketed = true; } } - $res = [Type::T_LIST, $sep, array_merge($list1[2], $list2[2])]; - if (isset($list1['enclosing'])) { - $res['enlcosing'] = $list1['enclosing']; - } + $res = [Type::T_LIST, $separator, array_merge($list1[2], $list2[2])]; + if ($bracketed) { $res['enclosing'] = 'bracket'; } + return $res; } - protected static $libAppend = ['list', 'val', 'separator:null']; + protected static $libAppend = ['list', 'val', 'separator:auto']; protected function libAppend($args) { list($list1, $value, $sep) = $args; - $list1 = $this->coerceList($list1, ' '); - $sep = $this->listSeparatorForJoin($list1, $sep); + $list1 = $this->coerceList($list1, ' ', true); + + switch ($this->compileStringContent($this->assertString($sep, 'separator'))) { + case 'comma': + $separator = ','; + break; + + case 'space': + $separator = ' '; + break; + + case 'slash': + $separator = '/'; + break; + + case 'auto': + $separator = $list1[1] === '' && \count($list1[2]) <= 1 && (empty($list1['enclosing']) || $list1['enclosing'] === 'parent') ? ' ' : $list1[1]; + break; + + default: + throw SassScriptException::forArgument('Must be "space", "comma", "slash", or "auto".', 'separator'); + } + + $res = [Type::T_LIST, $separator, array_merge($list1[2], [$value])]; - $res = [Type::T_LIST, $sep, array_merge($list1[2], [$value])]; if (isset($list1['enclosing'])) { $res['enclosing'] = $list1['enclosing']; } + return $res; } + protected static $libZip = ['lists...']; protected function libZip($args) { - foreach ($args as $key => $arg) { - $args[$key] = $this->coerceList($arg); + $argLists = []; + foreach ($args[0][2] as $arg) { + $argLists[] = $this->coerceList($arg); } $lists = []; - $firstList = array_shift($args); + $firstList = array_shift($argLists); - foreach ($firstList[2] as $key => $item) { - $list = [Type::T_LIST, '', [$item]]; + $result = [Type::T_LIST, ',', $lists]; + if (! \is_null($firstList)) { + foreach ($firstList[2] as $key => $item) { + $list = [Type::T_LIST, ' ', [$item]]; - foreach ($args as $arg) { - if (isset($arg[2][$key])) { - $list[2][] = $arg[2][$key]; - } else { - break 2; + foreach ($argLists as $arg) { + if (isset($arg[2][$key])) { + $list[2][] = $arg[2][$key]; + } else { + break 2; + } } + + $lists[] = $list; } - $lists[] = $list; + $result[2] = $lists; + } else { + $result['enclosing'] = 'parent'; } - return [Type::T_LIST, ',', $lists]; + return $result; } protected static $libTypeOf = ['value']; @@ -6688,6 +9297,16 @@ class Compiler { $value = $args[0]; + return [Type::T_KEYWORD, $this->getTypeOf($value)]; + } + + /** + * @param array|Number $value + * + * @return string + */ + private function getTypeOf($value) + { switch ($value[0]) { case Type::T_KEYWORD: if ($value === static::$true || $value === static::$false) { @@ -6702,8 +9321,11 @@ class Compiler case Type::T_FUNCTION: return 'string'; + case Type::T_FUNCTION_REFERENCE: + return 'function'; + case Type::T_LIST: - if (isset($value[3]) && $value[3]) { + if (isset($value[3]) && \is_array($value[3])) { return 'arglist'; } @@ -6716,68 +9338,77 @@ class Compiler protected static $libUnit = ['number']; protected function libUnit($args) { - $num = $args[0]; + $num = $this->assertNumber($args[0], 'number'); - if ($num[0] === Type::T_NUMBER) { - return [Type::T_STRING, '"', [$num->unitStr()]]; - } - - return ''; + return [Type::T_STRING, '"', [$num->unitStr()]]; } protected static $libUnitless = ['number']; protected function libUnitless($args) { - $value = $args[0]; + $value = $this->assertNumber($args[0], 'number'); - return $value[0] === Type::T_NUMBER && $value->unitless(); + return $this->toBool($value->unitless()); } - protected static $libComparable = ['number-1', 'number-2']; + protected static $libComparable = [ + ['number1', 'number2'], + ['number-1', 'number-2'] + ]; protected function libComparable($args) { list($number1, $number2) = $args; - if (! isset($number1[0]) || $number1[0] !== Type::T_NUMBER || - ! isset($number2[0]) || $number2[0] !== Type::T_NUMBER + if ( + ! $number1 instanceof Number || + ! $number2 instanceof Number ) { - $this->throwError('Invalid argument(s) for "comparable"'); - - return null; + throw $this->error('Invalid argument(s) for "comparable"'); } - $number1 = $number1->normalize(); - $number2 = $number2->normalize(); - - return $number1[2] === $number2[2] || $number1->unitless() || $number2->unitless(); + return $this->toBool($number1->isComparableTo($number2)); } protected static $libStrIndex = ['string', 'substring']; protected function libStrIndex($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'string'); $stringContent = $this->compileStringContent($string); - $substring = $this->coerceString($args[1]); + $substring = $this->assertString($args[1], 'substring'); $substringContent = $this->compileStringContent($substring); - $result = strpos($stringContent, $substringContent); + if (! \strlen($substringContent)) { + $result = 0; + } else { + $result = Util::mbStrpos($stringContent, $substringContent); + } - return $result === false ? static::$null : new Node\Number($result + 1, ''); + return $result === false ? static::$null : new Number($result + 1, ''); } protected static $libStrInsert = ['string', 'insert', 'index']; protected function libStrInsert($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'string'); $stringContent = $this->compileStringContent($string); - $insert = $this->coerceString($args[1]); + $insert = $this->assertString($args[1], 'insert'); $insertContent = $this->compileStringContent($insert); - list(, $index) = $args[2]; + $index = $this->assertInteger($args[2], 'index'); + if ($index > 0) { + $index = $index - 1; + } + if ($index < 0) { + $index = max(Util::mbStrlen($stringContent) + 1 + $index, 0); + } - $string[2] = [substr_replace($stringContent, $insertContent, $index - 1, 0)]; + $string[2] = [ + Util::mbSubstr($stringContent, 0, $index), + $insertContent, + Util::mbSubstr($stringContent, $index) + ]; return $string; } @@ -6785,34 +9416,46 @@ class Compiler protected static $libStrLength = ['string']; protected function libStrLength($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'string'); $stringContent = $this->compileStringContent($string); - return new Node\Number(strlen($stringContent), ''); + return new Number(Util::mbStrlen($stringContent), ''); } protected static $libStrSlice = ['string', 'start-at', 'end-at:-1']; protected function libStrSlice($args) { - if (isset($args[2]) && ! $args[2][1]) { - return static::$nullString; - } - - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'string'); $stringContent = $this->compileStringContent($string); - $start = (int) $args[1][1]; + $start = $this->assertNumber($args[1], 'start-at'); + $start->assertNoUnits('start-at'); + $startInt = $this->assertInteger($start, 'start-at'); + $end = $this->assertNumber($args[2], 'end-at'); + $end->assertNoUnits('end-at'); + $endInt = $this->assertInteger($end, 'end-at'); - if ($start > 0) { - $start--; + if ($endInt === 0) { + return [Type::T_STRING, $string[1], []]; } - $end = isset($args[2]) ? (int) $args[2][1] : -1; - $length = $end < 0 ? $end + 1 : ($end > 0 ? $end - $start : $end); + if ($startInt > 0) { + $startInt--; + } - $string[2] = $length - ? [substr($stringContent, $start, $length)] - : [substr($stringContent, $start)]; + if ($endInt < 0) { + $endInt = Util::mbStrlen($stringContent) + $endInt; + } else { + $endInt--; + } + + if ($endInt < $startInt) { + return [Type::T_STRING, $string[1], []]; + } + + $length = $endInt - $startInt + 1; // The end of the slice is inclusive + + $string[2] = [Util::mbSubstr($stringContent, $startInt, $length)]; return $string; } @@ -6820,10 +9463,10 @@ class Compiler protected static $libToLowerCase = ['string']; protected function libToLowerCase($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'string'); $stringContent = $this->compileStringContent($string); - $string[2] = [function_exists('mb_strtolower') ? mb_strtolower($stringContent) : strtolower($stringContent)]; + $string[2] = [$this->stringTransformAsciiOnly($stringContent, 'strtolower')]; return $string; } @@ -6831,75 +9474,103 @@ class Compiler protected static $libToUpperCase = ['string']; protected function libToUpperCase($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'string'); $stringContent = $this->compileStringContent($string); - $string[2] = [function_exists('mb_strtoupper') ? mb_strtoupper($stringContent) : strtoupper($stringContent)]; + $string[2] = [$this->stringTransformAsciiOnly($stringContent, 'strtoupper')]; return $string; } + /** + * Apply a filter on a string content, only on ascii chars + * let extended chars untouched + * + * @param string $stringContent + * @param callable $filter + * @return string + */ + protected function stringTransformAsciiOnly($stringContent, $filter) + { + $mblength = Util::mbStrlen($stringContent); + if ($mblength === strlen($stringContent)) { + return $filter($stringContent); + } + $filteredString = ""; + for ($i = 0; $i < $mblength; $i++) { + $char = Util::mbSubstr($stringContent, $i, 1); + if (strlen($char) > 1) { + $filteredString .= $char; + } else { + $filteredString .= $filter($char); + } + } + + return $filteredString; + } + protected static $libFeatureExists = ['feature']; protected function libFeatureExists($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'feature'); $name = $this->compileStringContent($string); return $this->toBool( - array_key_exists($name, $this->registeredFeatures) ? $this->registeredFeatures[$name] : false + \array_key_exists($name, $this->registeredFeatures) ? $this->registeredFeatures[$name] : false ); } protected static $libFunctionExists = ['name']; protected function libFunctionExists($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'name'); $name = $this->compileStringContent($string); // user defined functions if ($this->has(static::$namespaces['function'] . $name)) { - return true; + return self::$true; } $name = $this->normalizeName($name); if (isset($this->userFunctions[$name])) { - return true; + return self::$true; } // built-in functions $f = $this->getBuiltinFunction($name); - return $this->toBool(is_callable($f)); + return $this->toBool(\is_callable($f)); } protected static $libGlobalVariableExists = ['name']; protected function libGlobalVariableExists($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'name'); $name = $this->compileStringContent($string); - return $this->has($name, $this->rootEnv); + return $this->toBool($this->has($name, $this->rootEnv)); } protected static $libMixinExists = ['name']; protected function libMixinExists($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'name'); $name = $this->compileStringContent($string); - return $this->has(static::$namespaces['mixin'] . $name); + return $this->toBool($this->has(static::$namespaces['mixin'] . $name)); } protected static $libVariableExists = ['name']; protected function libVariableExists($args) { - $string = $this->coerceString($args[0]); + $string = $this->assertString($args[0], 'name'); $name = $this->compileStringContent($string); - return $this->has($name); + return $this->toBool($this->has($name)); } + protected static $libCounter = ['args...']; /** * Workaround IE7's content counter bug. * @@ -6909,35 +9580,37 @@ class Compiler */ protected function libCounter($args) { - $list = array_map([$this, 'compileValue'], $args); + $list = array_map([$this, 'compileValue'], $args[0][2]); return [Type::T_STRING, '', ['counter(' . implode(',', $list) . ')']]; } - protected static $libRandom = ['limit']; + protected static $libRandom = ['limit:null']; protected function libRandom($args) { - if (isset($args[0])) { - $n = $this->assertNumber($args[0]); + if (isset($args[0]) && $args[0] !== static::$null) { + $n = $this->assertInteger($args[0], 'limit'); if ($n < 1) { - $this->throwError("limit must be greater than or equal to 1"); - - return null; + throw new SassScriptException("\$limit: Must be greater than 0, was $n."); } - return new Node\Number(mt_rand(1, $n), ''); + return new Number(mt_rand(1, $n), ''); } - return new Node\Number(mt_rand(1, mt_getrandmax()), ''); + $max = mt_getrandmax(); + return new Number(mt_rand(0, $max - 1) / $max, ''); } + protected static $libUniqueId = []; protected function libUniqueId() { static $id; if (! isset($id)) { - $id = mt_rand(0, pow(36, 8)); + $id = PHP_INT_SIZE === 4 + ? mt_rand(0, pow(36, 5)) . str_pad(mt_rand(0, pow(36, 5)) % 10000000, 7, '0', STR_PAD_LEFT) + : mt_rand(0, pow(36, 8)); } $id += mt_rand(0, 10) + 1; @@ -6945,29 +9618,47 @@ class Compiler return [Type::T_STRING, '', ['u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)]]; } + /** + * @param array|Number $value + * @param bool $force_enclosing_display + * + * @return array + */ protected function inspectFormatValue($value, $force_enclosing_display = false) { if ($value === static::$null) { $value = [Type::T_KEYWORD, 'null']; } + $stringValue = [$value]; + + if ($value instanceof Number) { + return [Type::T_STRING, '', $stringValue]; + } + if ($value[0] === Type::T_LIST) { if (end($value[2]) === static::$null) { array_pop($value[2]); $value[2][] = [Type::T_STRING, '', ['']]; $force_enclosing_display = true; } - if (! empty($value['enclosing'])) { - if ($force_enclosing_display - || ($value['enclosing'] === 'bracket' ) - || !count($value[2])) { - $value['enclosing'] = 'forced_'.$value['enclosing']; - $force_enclosing_display = true; - } + + if ( + ! empty($value['enclosing']) && + ($force_enclosing_display || + ($value['enclosing'] === 'bracket') || + ! \count($value[2])) + ) { + $value['enclosing'] = 'forced_' . $value['enclosing']; + $force_enclosing_display = true; + } elseif (! \count($value[2])) { + $value['enclosing'] = 'forced_parent'; } + foreach ($value[2] as $k => $listelement) { $value[2][$k] = $this->inspectFormatValue($listelement, $force_enclosing_display); } + $stringValue = [$value]; } @@ -6978,37 +9669,80 @@ class Compiler protected function libInspect($args) { $value = $args[0]; + return $this->inspectFormatValue($value); } /** * Preprocess selector args * - * @param array $arg + * @param array $arg + * @param string|null $varname + * @param bool $allowParent * - * @return array|boolean + * @return array */ - protected function getSelectorArg($arg) + protected function getSelectorArg($arg, $varname = null, $allowParent = false) { static $parser = null; - if (is_null($parser)) { + if (\is_null($parser)) { $parser = $this->parserFactory(__METHOD__); } - $arg = $this->libUnquote([$arg]); + if (! $this->checkSelectorArgType($arg)) { + $var_value = $this->compileValue($arg); + throw SassScriptException::forArgument("$var_value is not a valid selector: it must be a string, a list of strings, or a list of lists of strings", $varname); + } + + + if ($arg[0] === Type::T_STRING) { + $arg[1] = ''; + } $arg = $this->compileValue($arg); $parsedSelector = []; - if ($parser->parseSelector($arg, $parsedSelector)) { + if ($parser->parseSelector($arg, $parsedSelector, true)) { $selector = $this->evalSelectors($parsedSelector); $gluedSelector = $this->glueFunctionSelectors($selector); + if (! $allowParent) { + foreach ($gluedSelector as $selector) { + foreach ($selector as $s) { + if (in_array(static::$selfSelector, $s)) { + throw SassScriptException::forArgument("Parent selectors aren't allowed here.", $varname); + } + } + } + } + return $gluedSelector; } - return false; + throw SassScriptException::forArgument("expected more input, invalid selector.", $varname); + } + + /** + * Check variable type for getSelectorArg() function + * @param array $arg + * @param int $maxDepth + * @return bool + */ + protected function checkSelectorArgType($arg, $maxDepth = 2) + { + if ($arg[0] === Type::T_LIST && $maxDepth > 0) { + foreach ($arg[2] as $elt) { + if (! $this->checkSelectorArgType($elt, $maxDepth - 1)) { + return false; + } + } + return true; + } + if (!in_array($arg[0], [Type::T_STRING, Type::T_KEYWORD])) { + return false; + } + return true; } /** @@ -7016,11 +9750,11 @@ class Compiler * * @param array $selectors * - * @return string + * @return array */ protected function formatOutputSelector($selectors) { - $selectors = $this->collapseSelectors($selectors, true); + $selectors = $this->collapseSelectorsAsList($selectors); return $selectors; } @@ -7030,10 +9764,10 @@ class Compiler { list($super, $sub) = $args; - $super = $this->getSelectorArg($super); - $sub = $this->getSelectorArg($sub); + $super = $this->getSelectorArg($super, 'super'); + $sub = $this->getSelectorArg($sub, 'sub'); - return $this->isSuperSelector($super, $sub); + return $this->toBool($this->isSuperSelector($super, $sub)); } /** @@ -7042,17 +9776,35 @@ class Compiler * @param array $super * @param array $sub * - * @return boolean + * @return bool */ protected function isSuperSelector($super, $sub) { // one and only one selector for each arg - if (! $super || count($super) !== 1) { - $this->throwError("Invalid super selector for isSuperSelector()"); + if (! $super) { + throw $this->error('Invalid super selector for isSuperSelector()'); } - if (! $sub || count($sub) !== 1) { - $this->throwError("Invalid sub selector for isSuperSelector()"); + if (! $sub) { + throw $this->error('Invalid sub selector for isSuperSelector()'); + } + + if (count($sub) > 1) { + foreach ($sub as $s) { + if (! $this->isSuperSelector($super, [$s])) { + return false; + } + } + return true; + } + + if (count($super) > 1) { + foreach ($super as $s) { + if ($this->isSuperSelector([$s], $sub)) { + return true; + } + } + return false; } $super = reset($super); @@ -7079,7 +9831,7 @@ class Compiler $nextMustMatch = true; $i++; } else { - while ($i < count($sub) && ! $this->isSuperPart($node, $sub[$i])) { + while ($i < \count($sub) && ! $this->isSuperPart($node, $sub[$i])) { if ($nextMustMatch) { return false; } @@ -7087,7 +9839,7 @@ class Compiler $i++; } - if ($i >= count($sub)) { + if ($i >= \count($sub)) { return false; } @@ -7105,18 +9857,18 @@ class Compiler * @param array $superParts * @param array $subParts * - * @return boolean + * @return bool */ protected function isSuperPart($superParts, $subParts) { $i = 0; foreach ($superParts as $superPart) { - while ($i < count($subParts) && $subParts[$i] !== $superPart) { + while ($i < \count($subParts) && $subParts[$i] !== $superPart) { $i++; } - if ($i >= count($subParts)) { + if ($i >= \count($subParts)) { return false; } @@ -7133,11 +9885,14 @@ class Compiler $args = reset($args); $args = $args[2]; - if (count($args) < 1) { - $this->throwError("selector-append() needs at least 1 argument"); + if (\count($args) < 1) { + throw $this->error('selector-append() needs at least 1 argument'); } - $selectors = array_map([$this, 'getSelectorArg'], $args); + $selectors = []; + foreach ($args as $arg) { + $selectors[] = $this->getSelectorArg($arg, 'selector'); + } return $this->formatOutputSelector($this->selectorAppend($selectors)); } @@ -7156,34 +9911,31 @@ class Compiler $lastSelectors = array_pop($selectors); if (! $lastSelectors) { - $this->throwError("Invalid selector list in selector-append()"); + throw $this->error('Invalid selector list in selector-append()'); } - while (count($selectors)) { + while (\count($selectors)) { $previousSelectors = array_pop($selectors); if (! $previousSelectors) { - $this->throwError("Invalid selector list in selector-append()"); + throw $this->error('Invalid selector list in selector-append()'); } // do the trick, happening $lastSelector to $previousSelector $appended = []; - foreach ($lastSelectors as $lastSelector) { - $previous = $previousSelectors; - - foreach ($lastSelector as $lastSelectorParts) { - foreach ($lastSelectorParts as $lastSelectorPart) { - foreach ($previous as $i => $previousSelector) { - foreach ($previousSelector as $j => $previousSelectorParts) { - $previous[$i][$j][] = $lastSelectorPart; + foreach ($previousSelectors as $previousSelector) { + foreach ($lastSelectors as $lastSelector) { + $previous = $previousSelector; + foreach ($previousSelector as $j => $previousSelectorParts) { + foreach ($lastSelector as $lastSelectorParts) { + foreach ($lastSelectorParts as $lastSelectorPart) { + $previous[$j][] = $lastSelectorPart; } } } - } - foreach ($previous as $ps) { - $appended[] = $ps; + $appended[] = $previous; } } @@ -7193,17 +9945,20 @@ class Compiler return $lastSelectors; } - protected static $libSelectorExtend = ['selectors', 'extendee', 'extender']; + protected static $libSelectorExtend = [ + ['selector', 'extendee', 'extender'], + ['selectors', 'extendee', 'extender'] + ]; protected function libSelectorExtend($args) { list($selectors, $extendee, $extender) = $args; - $selectors = $this->getSelectorArg($selectors); - $extendee = $this->getSelectorArg($extendee); - $extender = $this->getSelectorArg($extender); + $selectors = $this->getSelectorArg($selectors, 'selector'); + $extendee = $this->getSelectorArg($extendee, 'extendee'); + $extender = $this->getSelectorArg($extender, 'extender'); if (! $selectors || ! $extendee || ! $extender) { - $this->throwError("selector-extend() invalid arguments"); + throw $this->error('selector-extend() invalid arguments'); } $extended = $this->extendOrReplaceSelectors($selectors, $extendee, $extender); @@ -7211,17 +9966,20 @@ class Compiler return $this->formatOutputSelector($extended); } - protected static $libSelectorReplace = ['selectors', 'original', 'replacement']; + protected static $libSelectorReplace = [ + ['selector', 'original', 'replacement'], + ['selectors', 'original', 'replacement'] + ]; protected function libSelectorReplace($args) { list($selectors, $original, $replacement) = $args; - $selectors = $this->getSelectorArg($selectors); - $original = $this->getSelectorArg($original); - $replacement = $this->getSelectorArg($replacement); + $selectors = $this->getSelectorArg($selectors, 'selector'); + $original = $this->getSelectorArg($original, 'original'); + $replacement = $this->getSelectorArg($replacement, 'replacement'); if (! $selectors || ! $original || ! $replacement) { - $this->throwError("selector-replace() invalid arguments"); + throw $this->error('selector-replace() invalid arguments'); } $replaced = $this->extendOrReplaceSelectors($selectors, $original, $replacement, true); @@ -7233,10 +9991,10 @@ class Compiler * Extend/replace in selectors * used by selector-extend and selector-replace that use the same logic * - * @param array $selectors - * @param array $extendee - * @param array $extender - * @param boolean $replace + * @param array $selectors + * @param array $extendee + * @param array $extender + * @param bool $replace * * @return array */ @@ -7249,6 +10007,10 @@ class Compiler $this->extendsMap = []; foreach ($extendee as $es) { + if (\count($es) !== 1) { + throw $this->error('Can\'t extend complex selector.'); + } + // only use the first one $this->pushExtends(reset($es), $extender, null); } @@ -7260,12 +10022,12 @@ class Compiler $extended[] = $selector; } - $n = count($extended); + $n = \count($extended); $this->matchExtends($selector, $extended); // if didnt match, keep the original selector if we are in a replace operation - if ($replace and count($extended) === $n) { + if ($replace && \count($extended) === $n) { $extended[] = $selector; } } @@ -7283,11 +10045,17 @@ class Compiler $args = reset($args); $args = $args[2]; - if (count($args) < 1) { - $this->throwError("selector-nest() needs at least 1 argument"); + if (\count($args) < 1) { + throw $this->error('selector-nest() needs at least 1 argument'); } - $selectorsMap = array_map([$this, 'getSelectorArg'], $args); + $selectorsMap = []; + foreach ($args as $arg) { + $selectorsMap[] = $this->getSelectorArg($arg, 'selector', true); + } + + assert(!empty($selectorsMap)); + $envs = []; foreach ($selectorsMap as $selectors) { @@ -7304,11 +10072,14 @@ class Compiler return $this->formatOutputSelector($outputSelectors); } - protected static $libSelectorParse = ['selectors']; + protected static $libSelectorParse = [ + ['selector'], + ['selectors'] + ]; protected function libSelectorParse($args) { $selectors = reset($args); - $selectors = $this->getSelectorArg($selectors); + $selectors = $this->getSelectorArg($selectors, 'selector'); return $this->formatOutputSelector($selectors); } @@ -7318,11 +10089,11 @@ class Compiler { list($selectors1, $selectors2) = $args; - $selectors1 = $this->getSelectorArg($selectors1); - $selectors2 = $this->getSelectorArg($selectors2); + $selectors1 = $this->getSelectorArg($selectors1, 'selectors1'); + $selectors2 = $this->getSelectorArg($selectors2, 'selectors2'); if (! $selectors1 || ! $selectors2) { - $this->throwError("selector-unify() invalid arguments"); + throw $this->error('selector-unify() invalid arguments'); } // only consider the first compound of each @@ -7342,15 +10113,15 @@ class Compiler * @param array $compound1 * @param array $compound2 * - * @return array|mixed + * @return array */ protected function unifyCompoundSelectors($compound1, $compound2) { - if (! count($compound1)) { + if (! \count($compound1)) { return $compound2; } - if (! count($compound2)) { + if (! \count($compound2)) { return $compound1; } @@ -7367,7 +10138,7 @@ class Compiler $unifiedSelectors = [$unifiedCompound]; // do the rest - while (count($compound1) || count($compound2)) { + while (\count($compound1) || \count($compound2)) { $part1 = end($compound1); $part2 = end($compound2); @@ -7458,7 +10229,7 @@ class Compiler * @param array $part * @param array $compound * - * @return array|boolean + * @return array|false */ protected function matchPartInCompound($part, $compound) { @@ -7467,7 +10238,7 @@ class Compiler $after = []; // try to find a match by tag name first - while (count($before)) { + while (\count($before)) { $p = array_pop($before); if ($partTag && $partTag !== '*' && $partTag == $this->findTagName($p)) { @@ -7481,11 +10252,11 @@ class Compiler $before = $compound; $after = []; - while (count($before)) { + while (\count($before)) { $p = array_pop($before); if ($this->checkCompatibleTags($partTag, $this->findTagName($p))) { - if (count(array_intersect($part, $p))) { + if (\count(array_intersect($part, $p))) { return [$before, $p, $after]; } } @@ -7553,7 +10324,7 @@ class Compiler * @param string $tag1 * @param string $tag2 * - * @return array|boolean + * @return array|false */ protected function checkCompatibleTags($tag1, $tag2) { @@ -7561,12 +10332,12 @@ class Compiler $tags = array_unique($tags); $tags = array_filter($tags); - if (count($tags) > 1) { + if (\count($tags) > 1) { $tags = array_diff($tags, ['*']); } // not compatible nodes - if (count($tags) > 1) { + if (\count($tags) > 1) { return false; } @@ -7576,9 +10347,9 @@ class Compiler /** * Find the html tag name in a selector parts list * - * @param array $parts + * @param string[] $parts * - * @return mixed|string + * @return string */ protected function findTagName($parts) { @@ -7595,7 +10366,7 @@ class Compiler protected function libSimpleSelectors($args) { $selector = reset($args); - $selector = $this->getSelectorArg($selector); + $selector = $this->getSelectorArg($selector, 'selector'); // remove selectors list layer, keeping the first one $selector = reset($selector); @@ -7611,4 +10382,27 @@ class Compiler return [Type::T_LIST, ',', $listParts]; } + + protected static $libScssphpGlob = ['pattern']; + protected function libScssphpGlob($args) + { + @trigger_error(sprintf('The "scssphp-glob" function is deprecated an will be removed in ScssPhp 2.0. Register your own alternative through "%s::registerFunction', __CLASS__), E_USER_DEPRECATED); + + $this->logger->warn('The "scssphp-glob" function is deprecated an will be removed in ScssPhp 2.0.', true); + + $string = $this->assertString($args[0], 'pattern'); + $pattern = $this->compileStringContent($string); + $matches = glob($pattern); + $listParts = []; + + foreach ($matches as $match) { + if (! is_file($match)) { + continue; + } + + $listParts[] = [Type::T_STRING, '"', [$match]]; + } + + return [Type::T_LIST, ',', $listParts]; + } } diff --git a/lib/scssphp/scssphp/src/Compiler/CachedResult.php b/lib/scssphp/scssphp/src/Compiler/CachedResult.php new file mode 100644 index 000000000..a66291996 --- /dev/null +++ b/lib/scssphp/scssphp/src/Compiler/CachedResult.php @@ -0,0 +1,77 @@ + + */ + private $parsedFiles; + + /** + * @var array + * @phpstan-var list + */ + private $resolvedImports; + + /** + * @param CompilationResult $result + * @param array $parsedFiles + * @param array $resolvedImports + * + * @phpstan-param list $resolvedImports + */ + public function __construct(CompilationResult $result, array $parsedFiles, array $resolvedImports) + { + $this->result = $result; + $this->parsedFiles = $parsedFiles; + $this->resolvedImports = $resolvedImports; + } + + /** + * @return CompilationResult + */ + public function getResult() + { + return $this->result; + } + + /** + * @return array + */ + public function getParsedFiles() + { + return $this->parsedFiles; + } + + /** + * @return array + * + * @phpstan-return list + */ + public function getResolvedImports() + { + return $this->resolvedImports; + } +} diff --git a/lib/scssphp/scssphp/src/Compiler/Environment.php b/lib/scssphp/scssphp/src/Compiler/Environment.php index 03eb86a5d..b205a077f 100644 --- a/lib/scssphp/scssphp/src/Compiler/Environment.php +++ b/lib/scssphp/scssphp/src/Compiler/Environment.php @@ -1,8 +1,9 @@ + * + * @internal */ class Environment { /** - * @var \ScssPhp\ScssPhp\Block + * @var \ScssPhp\ScssPhp\Block|null */ public $block; /** - * @var \ScssPhp\ScssPhp\Compiler\Environment + * @var \ScssPhp\ScssPhp\Compiler\Environment|null */ public $parent; + /** + * @var Environment|null + */ + public $declarationScopeParent; + + /** + * @var Environment|null + */ + public $parentStore; + + /** + * @var array|null + */ + public $selectors; + + /** + * @var string|null + */ + public $marker; + /** * @var array */ @@ -39,7 +62,7 @@ class Environment public $storeUnreduced; /** - * @var integer + * @var int */ public $depth; } diff --git a/lib/scssphp/scssphp/src/Exception/CompilerException.php b/lib/scssphp/scssphp/src/Exception/CompilerException.php index a9d134fca..0b00cf525 100644 --- a/lib/scssphp/scssphp/src/Exception/CompilerException.php +++ b/lib/scssphp/scssphp/src/Exception/CompilerException.php @@ -1,8 +1,9 @@ + * + * @internal */ -class CompilerException extends \Exception +class CompilerException extends \Exception implements SassException { } diff --git a/lib/scssphp/scssphp/src/Exception/ParserException.php b/lib/scssphp/scssphp/src/Exception/ParserException.php index 2fa12dd7a..f0726698f 100644 --- a/lib/scssphp/scssphp/src/Exception/ParserException.php +++ b/lib/scssphp/scssphp/src/Exception/ParserException.php @@ -1,8 +1,9 @@ + * + * @internal */ -class ParserException extends \Exception +class ParserException extends \Exception implements SassException { + /** + * @var array|null + * @phpstan-var array{string, int, int}|null + */ + private $sourcePosition; + + /** + * Get source position + * + * @api + * + * @return array|null + * @phpstan-return array{string, int, int}|null + */ + public function getSourcePosition() + { + return $this->sourcePosition; + } + + /** + * Set source position + * + * @api + * + * @param array $sourcePosition + * + * @return void + * + * @phpstan-param array{string, int, int} $sourcePosition + */ + public function setSourcePosition($sourcePosition) + { + $this->sourcePosition = $sourcePosition; + } } diff --git a/lib/scssphp/scssphp/src/Exception/RangeException.php b/lib/scssphp/scssphp/src/Exception/RangeException.php index ee36c97e1..4be4dee70 100644 --- a/lib/scssphp/scssphp/src/Exception/RangeException.php +++ b/lib/scssphp/scssphp/src/Exception/RangeException.php @@ -1,8 +1,9 @@ + * + * @internal */ -class RangeException extends \Exception +class RangeException extends \Exception implements SassException { } diff --git a/lib/scssphp/scssphp/src/Exception/SassException.php b/lib/scssphp/scssphp/src/Exception/SassException.php new file mode 100644 index 000000000..9f62b3cd2 --- /dev/null +++ b/lib/scssphp/scssphp/src/Exception/SassException.php @@ -0,0 +1,7 @@ + + * + * @deprecated The Scssphp server should define its own exception instead. */ -class ServerException extends \Exception +class ServerException extends \Exception implements SassException { } diff --git a/lib/scssphp/scssphp/src/Formatter.php b/lib/scssphp/scssphp/src/Formatter.php index e17770458..6137dc650 100644 --- a/lib/scssphp/scssphp/src/Formatter.php +++ b/lib/scssphp/scssphp/src/Formatter.php @@ -1,8 +1,9 @@ + * + * @internal */ abstract class Formatter { /** - * @var integer + * @var int */ public $indentLevel; @@ -57,7 +60,7 @@ abstract class Formatter public $assignSeparator; /** - * @var boolean + * @var bool */ public $keepSemicolons; @@ -67,17 +70,17 @@ abstract class Formatter protected $currentBlock; /** - * @var integer + * @var int */ protected $currentLine; /** - * @var integer + * @var int */ protected $currentColumn; /** - * @var \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator + * @var \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator|null */ protected $sourceMapGenerator; @@ -118,16 +121,33 @@ abstract class Formatter return rtrim($name) . $this->assignSeparator . $value . ';'; } + /** + * Return custom property assignment + * differs in that you have to keep spaces in the value as is + * + * @api + * + * @param string $name + * @param mixed $value + * + * @return string + */ + public function customProperty($name, $value) + { + return rtrim($name) . trim($this->assignSeparator) . $value . ';'; + } + /** * Output lines inside a block * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block + * + * @return void */ protected function blockLines(OutputBlock $block) { $inner = $this->indentStr(); - - $glue = $this->break . $inner; + $glue = $this->break . $inner; $this->write($inner . implode($glue, $block->lines)); @@ -140,9 +160,13 @@ abstract class Formatter * Output block selectors * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block + * + * @return void */ protected function blockSelectors(OutputBlock $block) { + assert(! empty($block->selectors)); + $inner = $this->indentStr(); $this->write($inner @@ -154,6 +178,8 @@ abstract class Formatter * Output block children * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block + * + * @return void */ protected function blockChildren(OutputBlock $block) { @@ -166,6 +192,8 @@ abstract class Formatter * Output non-empty block * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block + * + * @return void */ protected function block(OutputBlock $block) { @@ -211,7 +239,7 @@ abstract class Formatter * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block * - * @return boolean + * @return bool */ protected function testEmptyChildren($block) { @@ -258,9 +286,18 @@ abstract class Formatter ob_start(); - $this->block($block); + try { + $this->block($block); + } catch (\Exception $e) { + ob_end_clean(); + throw $e; + } catch (\Throwable $e) { + ob_end_clean(); + throw $e; + } $out = ob_get_clean(); + assert($out !== false); return $out; } @@ -269,6 +306,8 @@ abstract class Formatter * Output content * * @param string $str + * + * @return void */ protected function write($str) { @@ -282,7 +321,8 @@ abstract class Formatter * Maybe Strip semi-colon appended by property(); it's a separator, not a terminator * will be striped for real before a closing, otherwise displayed unchanged starting the next write */ - if (! $this->keepSemicolons && + if ( + ! $this->keepSemicolons && $str && (strpos($str, ';') !== false) && (substr($str, -1) === ';') @@ -293,22 +333,43 @@ abstract class Formatter } if ($this->sourceMapGenerator) { - $this->sourceMapGenerator->addMapping( - $this->currentLine, - $this->currentColumn, - $this->currentBlock->sourceLine, - //columns from parser are off by one - $this->currentBlock->sourceColumn > 0 ? $this->currentBlock->sourceColumn - 1 : 0, - $this->currentBlock->sourceName - ); - $lines = explode("\n", $str); - $lineCount = count($lines); - $this->currentLine += $lineCount-1; - $lastLine = array_pop($lines); - $this->currentColumn = ($lineCount === 1 ? $this->currentColumn : 0) + strlen($lastLine); + foreach ($lines as $line) { + // If the written line starts is empty, adding a mapping would add it for + // a non-existent column as we are at the end of the line + if ($line !== '') { + assert($this->currentBlock->sourceLine !== null); + assert($this->currentBlock->sourceName !== null); + $this->sourceMapGenerator->addMapping( + $this->currentLine, + $this->currentColumn, + $this->currentBlock->sourceLine, + //columns from parser are off by one + $this->currentBlock->sourceColumn > 0 ? $this->currentBlock->sourceColumn - 1 : 0, + $this->currentBlock->sourceName + ); + } + + $this->currentLine++; + $this->currentColumn = 0; + } + + if ($lastLine !== '') { + assert($this->currentBlock->sourceLine !== null); + assert($this->currentBlock->sourceName !== null); + $this->sourceMapGenerator->addMapping( + $this->currentLine, + $this->currentColumn, + $this->currentBlock->sourceLine, + //columns from parser are off by one + $this->currentBlock->sourceColumn > 0 ? $this->currentBlock->sourceColumn - 1 : 0, + $this->currentBlock->sourceName + ); + } + + $this->currentColumn += \strlen($lastLine); } echo $str; diff --git a/lib/scssphp/scssphp/src/Formatter/Compact.php b/lib/scssphp/scssphp/src/Formatter/Compact.php index 591f0c92e..22f226889 100644 --- a/lib/scssphp/scssphp/src/Formatter/Compact.php +++ b/lib/scssphp/scssphp/src/Formatter/Compact.php @@ -1,8 +1,9 @@ + * + * @deprecated since 1.4.0. Use the Compressed formatter instead. + * + * @internal */ class Compact extends Formatter { @@ -25,6 +30,8 @@ class Compact extends Formatter */ public function __construct() { + @trigger_error('The Compact formatter is deprecated since 1.4.0. Use the Compressed formatter instead.', E_USER_DEPRECATED); + $this->indentLevel = 0; $this->indentChar = ''; $this->break = ''; diff --git a/lib/scssphp/scssphp/src/Formatter/Compressed.php b/lib/scssphp/scssphp/src/Formatter/Compressed.php index ec4722eaf..58ebe3f11 100644 --- a/lib/scssphp/scssphp/src/Formatter/Compressed.php +++ b/lib/scssphp/scssphp/src/Formatter/Compressed.php @@ -1,8 +1,9 @@ + * + * @internal */ class Compressed extends Formatter { @@ -48,8 +50,6 @@ class Compressed extends Formatter foreach ($block->lines as $index => $line) { if (substr($line, 0, 2) === '/*' && substr($line, 2, 1) !== '!') { unset($block->lines[$index]); - } elseif (substr($line, 0, 3) === '/*!') { - $block->lines[$index] = '/*' . substr($line, 3); } } @@ -67,6 +67,8 @@ class Compressed extends Formatter */ protected function blockSelectors(OutputBlock $block) { + assert(! empty($block->selectors)); + $inner = $this->indentStr(); $this->write( diff --git a/lib/scssphp/scssphp/src/Formatter/Crunched.php b/lib/scssphp/scssphp/src/Formatter/Crunched.php index 51ccb516d..2bc1e9299 100644 --- a/lib/scssphp/scssphp/src/Formatter/Crunched.php +++ b/lib/scssphp/scssphp/src/Formatter/Crunched.php @@ -1,8 +1,9 @@ + * + * @deprecated since 1.4.0. Use the Compressed formatter instead. + * + * @internal */ class Crunched extends Formatter { @@ -26,6 +30,8 @@ class Crunched extends Formatter */ public function __construct() { + @trigger_error('The Crunched formatter is deprecated since 1.4.0. Use the Compressed formatter instead.', E_USER_DEPRECATED); + $this->indentLevel = 0; $this->indentChar = ' '; $this->break = ''; @@ -65,6 +71,8 @@ class Crunched extends Formatter */ protected function blockSelectors(OutputBlock $block) { + assert(! empty($block->selectors)); + $inner = $this->indentStr(); $this->write( diff --git a/lib/scssphp/scssphp/src/Formatter/Debug.php b/lib/scssphp/scssphp/src/Formatter/Debug.php index 94e70c815..b3f442253 100644 --- a/lib/scssphp/scssphp/src/Formatter/Debug.php +++ b/lib/scssphp/scssphp/src/Formatter/Debug.php @@ -1,8 +1,9 @@ + * + * @deprecated since 1.4.0. + * + * @internal */ class Debug extends Formatter { @@ -26,6 +30,8 @@ class Debug extends Formatter */ public function __construct() { + @trigger_error('The Debug formatter is deprecated since 1.4.0.', E_USER_DEPRECATED); + $this->indentLevel = 0; $this->indentChar = ''; $this->break = "\n"; diff --git a/lib/scssphp/scssphp/src/Formatter/Expanded.php b/lib/scssphp/scssphp/src/Formatter/Expanded.php index 9549c6cfa..6eb4a0cb7 100644 --- a/lib/scssphp/scssphp/src/Formatter/Expanded.php +++ b/lib/scssphp/scssphp/src/Formatter/Expanded.php @@ -1,8 +1,9 @@ + * + * @internal */ class Expanded extends Formatter { @@ -55,7 +57,9 @@ class Expanded extends Formatter foreach ($block->lines as $index => $line) { if (substr($line, 0, 2) === '/*') { - $block->lines[$index] = preg_replace('/[\r\n]+/', $glue, $line); + $replacedLine = preg_replace('/\r\n?|\n|\f/', $this->break, $line); + assert($replacedLine !== null); + $block->lines[$index] = $replacedLine; } } diff --git a/lib/scssphp/scssphp/src/Formatter/Nested.php b/lib/scssphp/scssphp/src/Formatter/Nested.php index f9e7f037f..d5ed85cc2 100644 --- a/lib/scssphp/scssphp/src/Formatter/Nested.php +++ b/lib/scssphp/scssphp/src/Formatter/Nested.php @@ -1,8 +1,9 @@ + * + * @deprecated since 1.4.0. Use the Expanded formatter instead. + * + * @internal */ class Nested extends Formatter { /** - * @var integer + * @var int */ private $depth; @@ -32,6 +36,8 @@ class Nested extends Formatter */ public function __construct() { + @trigger_error('The Nested formatter is deprecated since 1.4.0. Use the Expanded formatter instead.', E_USER_DEPRECATED); + $this->indentLevel = 0; $this->indentChar = ' '; $this->break = "\n"; @@ -58,12 +64,13 @@ class Nested extends Formatter protected function blockLines(OutputBlock $block) { $inner = $this->indentStr(); - - $glue = $this->break . $inner; + $glue = $this->break . $inner; foreach ($block->lines as $index => $line) { if (substr($line, 0, 2) === '/*') { - $block->lines[$index] = preg_replace('/[\r\n]+/', $glue, $line); + $replacedLine = preg_replace('/\r\n?|\n|\f/', $this->break, $line); + assert($replacedLine !== null); + $block->lines[$index] = $replacedLine; } } @@ -90,7 +97,7 @@ class Nested extends Formatter $previousHasSelector = false; } - $isMediaOrDirective = in_array($block->type, [Type::T_DIRECTIVE, Type::T_MEDIA]); + $isMediaOrDirective = \in_array($block->type, [Type::T_DIRECTIVE, Type::T_MEDIA]); $isSupport = ($block->type === Type::T_DIRECTIVE && $block->selectors && strpos(implode('', $block->selectors), '@supports') !== false); @@ -98,7 +105,8 @@ class Nested extends Formatter array_pop($depths); $this->depth--; - if (! $this->depth && ($block->depth <= 1 || (! $this->indentLevel && $block->type === Type::T_COMMENT)) && + if ( + ! $this->depth && ($block->depth <= 1 || (! $this->indentLevel && $block->type === Type::T_COMMENT)) && (($block->selectors && ! $isMediaOrDirective) || $previousHasSelector) ) { $downLevel = $this->break; @@ -119,10 +127,12 @@ class Nested extends Formatter if ($block->depth > end($depths)) { if (! $previousEmpty || $this->depth < 1) { $this->depth++; + $depths[] = $block->depth; } else { // keep the current depth unchanged but take the block depth as a new reference for following blocks array_pop($depths); + $depths[] = $block->depth; } } @@ -213,7 +223,7 @@ class Nested extends Formatter * * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block * - * @return boolean + * @return bool */ private function hasFlatChild($block) { diff --git a/lib/scssphp/scssphp/src/Formatter/OutputBlock.php b/lib/scssphp/scssphp/src/Formatter/OutputBlock.php index 3e6fd9289..2799656a4 100644 --- a/lib/scssphp/scssphp/src/Formatter/OutputBlock.php +++ b/lib/scssphp/scssphp/src/Formatter/OutputBlock.php @@ -1,8 +1,9 @@ + * + * @internal */ class OutputBlock { /** - * @var string + * @var string|null */ public $type; /** - * @var integer + * @var int */ public $depth; /** - * @var array + * @var array|null */ public $selectors; /** - * @var array + * @var string[] */ public $lines; /** - * @var array + * @var OutputBlock[] */ public $children; /** - * @var \ScssPhp\ScssPhp\Formatter\OutputBlock + * @var OutputBlock|null */ public $parent; /** - * @var string + * @var string|null */ public $sourceName; /** - * @var integer + * @var int|null */ public $sourceLine; /** - * @var integer + * @var int|null */ public $sourceColumn; } diff --git a/lib/scssphp/scssphp/src/Logger/LoggerInterface.php b/lib/scssphp/scssphp/src/Logger/LoggerInterface.php new file mode 100644 index 000000000..7c0a2f76e --- /dev/null +++ b/lib/scssphp/scssphp/src/Logger/LoggerInterface.php @@ -0,0 +1,48 @@ +stream = $stream; + $this->closeOnDestruct = $closeOnDestruct; + } + + /** + * @internal + */ + public function __destruct() + { + if ($this->closeOnDestruct) { + fclose($this->stream); + } + } + + /** + * @inheritDoc + */ + public function warn($message, $deprecation = false) + { + $prefix = ($deprecation ? 'DEPRECATION ' : '') . 'WARNING: '; + + fwrite($this->stream, $prefix . $message . "\n\n"); + } + + /** + * @inheritDoc + */ + public function debug($message) + { + fwrite($this->stream, $message . "\n"); + } +} diff --git a/lib/scssphp/scssphp/src/Node.php b/lib/scssphp/scssphp/src/Node.php index dab565a63..fcaf8a95f 100644 --- a/lib/scssphp/scssphp/src/Node.php +++ b/lib/scssphp/scssphp/src/Node.php @@ -1,8 +1,9 @@ + * + * @internal */ abstract class Node { @@ -24,17 +27,17 @@ abstract class Node public $type; /** - * @var integer + * @var int */ public $sourceIndex; /** - * @var integer + * @var int|null */ public $sourceLine; /** - * @var integer + * @var int|null */ public $sourceColumn; } diff --git a/lib/scssphp/scssphp/src/Node/Number.php b/lib/scssphp/scssphp/src/Node/Number.php index acbabff7f..ca9b5b652 100644 --- a/lib/scssphp/scssphp/src/Node/Number.php +++ b/lib/scssphp/scssphp/src/Node/Number.php @@ -1,8 +1,9 @@ + * + * @template-implements \ArrayAccess */ class Number extends Node implements \ArrayAccess { + const PRECISION = 10; + /** - * @var integer + * @var int + * @deprecated use {Number::PRECISION} instead to read the precision. Configuring it is not supported anymore. */ - static public $precision = 10; + public static $precision = self::PRECISION; /** * @see http://www.w3.org/TR/2012/WD-css3-values-20120308/ * * @var array + * @phpstan-var array> */ - static protected $unitTable = [ + protected static $unitTable = [ 'in' => [ 'in' => 1, 'pc' => 6, @@ -64,91 +75,93 @@ class Number extends Node implements \ArrayAccess ], 'dpi' => [ 'dpi' => 1, - 'dpcm' => 2.54, - 'dppx' => 96, + 'dpcm' => 1 / 2.54, + 'dppx' => 1 / 96, ], ]; /** - * @var integer|float + * @var int|float */ - public $dimension; + private $dimension; /** - * @var array + * @var string[] + * @phpstan-var list */ - public $units; + private $numeratorUnits; + + /** + * @var string[] + * @phpstan-var list + */ + private $denominatorUnits; /** * Initialize number * - * @param mixed $dimension - * @param mixed $initialUnit + * @param int|float $dimension + * @param string[]|string $numeratorUnits + * @param string[] $denominatorUnits + * + * @phpstan-param list|string $numeratorUnits + * @phpstan-param list $denominatorUnits */ - public function __construct($dimension, $initialUnit) + public function __construct($dimension, $numeratorUnits, array $denominatorUnits = []) { - $this->type = Type::T_NUMBER; + if (is_string($numeratorUnits)) { + $numeratorUnits = $numeratorUnits ? [$numeratorUnits] : []; + } elseif (isset($numeratorUnits['numerator_units'], $numeratorUnits['denominator_units'])) { + // TODO get rid of this once `$number[2]` is not used anymore + $denominatorUnits = $numeratorUnits['denominator_units']; + $numeratorUnits = $numeratorUnits['numerator_units']; + } + $this->dimension = $dimension; - $this->units = is_array($initialUnit) - ? $initialUnit - : ($initialUnit ? [$initialUnit => 1] - : []); + $this->numeratorUnits = $numeratorUnits; + $this->denominatorUnits = $denominatorUnits; } /** - * Coerce number to target units - * - * @param array $units - * - * @return \ScssPhp\ScssPhp\Node\Number + * @return float|int */ - public function coerce($units) + public function getDimension() { - if ($this->unitless()) { - return new Number($this->dimension, $units); - } - - $dimension = $this->dimension; - - foreach (static::$unitTable['in'] as $unit => $conv) { - $from = isset($this->units[$unit]) ? $this->units[$unit] : 0; - $to = isset($units[$unit]) ? $units[$unit] : 0; - $factor = pow($conv, $from - $to); - $dimension /= $factor; - } - - return new Number($dimension, $units); + return $this->dimension; } /** - * Normalize number - * - * @return \ScssPhp\ScssPhp\Node\Number + * @return string[] */ - public function normalize() + public function getNumeratorUnits() { - $dimension = $this->dimension; - $units = []; - - $this->normalizeUnits($dimension, $units, 'in'); - - return new Number($dimension, $units); + return $this->numeratorUnits; } /** - * {@inheritdoc} + * @return string[] */ + public function getDenominatorUnits() + { + return $this->denominatorUnits; + } + + /** + * @return bool + */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { if ($offset === -3) { - return ! is_null($this->sourceColumn); + return ! \is_null($this->sourceColumn); } if ($offset === -2) { - return ! is_null($this->sourceLine); + return ! \is_null($this->sourceLine); } - if ($offset === -1 || + if ( + $offset === -1 || $offset === 0 || $offset === 1 || $offset === 2 @@ -160,8 +173,9 @@ class Number extends Node implements \ArrayAccess } /** - * {@inheritdoc} + * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { switch ($offset) { @@ -175,60 +189,54 @@ class Number extends Node implements \ArrayAccess return $this->sourceIndex; case 0: - return $this->type; + return Type::T_NUMBER; case 1: return $this->dimension; case 2: - return $this->units; + return array('numerator_units' => $this->numeratorUnits, 'denominator_units' => $this->denominatorUnits); } } /** - * {@inheritdoc} + * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { - if ($offset === 1) { - $this->dimension = $value; - } elseif ($offset === 2) { - $this->units = $value; - } elseif ($offset == -1) { - $this->sourceIndex = $value; - } elseif ($offset == -2) { - $this->sourceLine = $value; - } elseif ($offset == -3) { - $this->sourceColumn = $value; - } + throw new \BadMethodCallException('Number is immutable'); } /** - * {@inheritdoc} + * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { - if ($offset === 1) { - $this->dimension = null; - } elseif ($offset === 2) { - $this->units = null; - } elseif ($offset === -1) { - $this->sourceIndex = null; - } elseif ($offset === -2) { - $this->sourceLine = null; - } elseif ($offset === -3) { - $this->sourceColumn = null; - } + throw new \BadMethodCallException('Number is immutable'); } /** * Returns true if the number is unitless * - * @return boolean + * @return bool */ public function unitless() { - return ! array_sum($this->units); + return \count($this->numeratorUnits) === 0 && \count($this->denominatorUnits) === 0; + } + + /** + * Checks whether the number has exactly this unit + * + * @param string $unit + * + * @return bool + */ + public function hasUnit($unit) + { + return \count($this->numeratorUnits) === 1 && \count($this->denominatorUnits) === 0 && $this->numeratorUnits[0] === $unit; } /** @@ -238,22 +246,289 @@ class Number extends Node implements \ArrayAccess */ public function unitStr() { - $numerators = []; - $denominators = []; - - foreach ($this->units as $unit => $unitSize) { - if ($unitSize > 0) { - $numerators = array_pad($numerators, count($numerators) + $unitSize, $unit); - continue; - } - - if ($unitSize < 0) { - $denominators = array_pad($denominators, count($denominators) + $unitSize, $unit); - continue; - } + if ($this->unitless()) { + return ''; } - return implode('*', $numerators) . (count($denominators) ? '/' . implode('*', $denominators) : ''); + return self::getUnitString($this->numeratorUnits, $this->denominatorUnits); + } + + /** + * @param float|int $min + * @param float|int $max + * @param string|null $name + * + * @return float|int + * @throws SassScriptException + */ + public function valueInRange($min, $max, $name = null) + { + try { + return Util::checkRange('', new Range($min, $max), $this); + } catch (RangeException $e) { + throw SassScriptException::forArgument(sprintf('Expected %s to be within %s%s and %s%3$s', $this, $min, $this->unitStr(), $max), $name); + } + } + + /** + * @param string|null $varName + * + * @return void + */ + public function assertNoUnits($varName = null) + { + if ($this->unitless()) { + return; + } + + throw SassScriptException::forArgument(sprintf('Expected %s to have no units.', $this), $varName); + } + + /** + * @param string $unit + * @param string|null $varName + * + * @return void + */ + public function assertUnit($unit, $varName = null) + { + if ($this->hasUnit($unit)) { + return; + } + + throw SassScriptException::forArgument(sprintf('Expected %s to have unit "%s".', $this, $unit), $varName); + } + + /** + * @param Number $other + * + * @return void + */ + public function assertSameUnitOrUnitless(Number $other) + { + if ($other->unitless()) { + return; + } + + if ($this->numeratorUnits === $other->numeratorUnits && $this->denominatorUnits === $other->denominatorUnits) { + return; + } + + throw new SassScriptException(sprintf( + 'Incompatible units %s and %s.', + self::getUnitString($this->numeratorUnits, $this->denominatorUnits), + self::getUnitString($other->numeratorUnits, $other->denominatorUnits) + )); + } + + /** + * Returns a copy of this number, converted to the units represented by $newNumeratorUnits and $newDenominatorUnits. + * + * This does not throw an error if this number is unitless and + * $newNumeratorUnits/$newDenominatorUnits are not empty, or vice versa. Instead, + * it treats all unitless numbers as convertible to and from all units without + * changing the value. + * + * @param string[] $newNumeratorUnits + * @param string[] $newDenominatorUnits + * + * @return Number + * + * @phpstan-param list $newNumeratorUnits + * @phpstan-param list $newDenominatorUnits + * + * @throws SassScriptException if this number's units are not compatible with $newNumeratorUnits and $newDenominatorUnits + */ + public function coerce(array $newNumeratorUnits, array $newDenominatorUnits) + { + return new Number($this->valueInUnits($newNumeratorUnits, $newDenominatorUnits), $newNumeratorUnits, $newDenominatorUnits); + } + + /** + * @param Number $other + * + * @return bool + */ + public function isComparableTo(Number $other) + { + if ($this->unitless() || $other->unitless()) { + return true; + } + + try { + $this->greaterThan($other); + return true; + } catch (SassScriptException $e) { + return false; + } + } + + /** + * @param Number $other + * + * @return bool + */ + public function lessThan(Number $other) + { + return $this->coerceUnits($other, function ($num1, $num2) { + return $num1 < $num2; + }); + } + + /** + * @param Number $other + * + * @return bool + */ + public function lessThanOrEqual(Number $other) + { + return $this->coerceUnits($other, function ($num1, $num2) { + return $num1 <= $num2; + }); + } + + /** + * @param Number $other + * + * @return bool + */ + public function greaterThan(Number $other) + { + return $this->coerceUnits($other, function ($num1, $num2) { + return $num1 > $num2; + }); + } + + /** + * @param Number $other + * + * @return bool + */ + public function greaterThanOrEqual(Number $other) + { + return $this->coerceUnits($other, function ($num1, $num2) { + return $num1 >= $num2; + }); + } + + /** + * @param Number $other + * + * @return Number + */ + public function plus(Number $other) + { + return $this->coerceNumber($other, function ($num1, $num2) { + return $num1 + $num2; + }); + } + + /** + * @param Number $other + * + * @return Number + */ + public function minus(Number $other) + { + return $this->coerceNumber($other, function ($num1, $num2) { + return $num1 - $num2; + }); + } + + /** + * @return Number + */ + public function unaryMinus() + { + return new Number(-$this->dimension, $this->numeratorUnits, $this->denominatorUnits); + } + + /** + * @param Number $other + * + * @return Number + */ + public function modulo(Number $other) + { + return $this->coerceNumber($other, function ($num1, $num2) { + if ($num2 == 0) { + return NAN; + } + + $result = fmod($num1, $num2); + + if ($result == 0) { + return 0; + } + + if ($num2 < 0 xor $num1 < 0) { + $result += $num2; + } + + return $result; + }); + } + + /** + * @param Number $other + * + * @return Number + */ + public function times(Number $other) + { + return $this->multiplyUnits($this->dimension * $other->dimension, $this->numeratorUnits, $this->denominatorUnits, $other->numeratorUnits, $other->denominatorUnits); + } + + /** + * @param Number $other + * + * @return Number + */ + public function dividedBy(Number $other) + { + if ($other->dimension == 0) { + if ($this->dimension == 0) { + $value = NAN; + } elseif ($this->dimension > 0) { + $value = INF; + } else { + $value = -INF; + } + } else { + $value = $this->dimension / $other->dimension; + } + + return $this->multiplyUnits($value, $this->numeratorUnits, $this->denominatorUnits, $other->denominatorUnits, $other->numeratorUnits); + } + + /** + * @param Number $other + * + * @return bool + */ + public function equals(Number $other) + { + // Unitless numbers are convertable to unit numbers, but not equal, so we special-case unitless here. + if ($this->unitless() !== $other->unitless()) { + return false; + } + + // In Sass, neither NaN nor Infinity are equal to themselves, while PHP defines INF==INF + if (is_nan($this->dimension) || is_nan($other->dimension) || !is_finite($this->dimension) || !is_finite($other->dimension)) { + return false; + } + + if ($this->unitless()) { + return round($this->dimension, self::PRECISION) == round($other->dimension, self::PRECISION); + } + + try { + return $this->coerceUnits($other, function ($num1, $num2) { + return round($num1,self::PRECISION) == round($num2, self::PRECISION); + }); + } catch (SassScriptException $e) { + return false; + } } /** @@ -265,35 +540,31 @@ class Number extends Node implements \ArrayAccess */ public function output(Compiler $compiler = null) { - $dimension = round($this->dimension, static::$precision); + $dimension = round($this->dimension, self::PRECISION); - $units = array_filter($this->units, function ($unitSize) { - return $unitSize; - }); - - if (count($units) > 1 && array_sum($units) === 0) { - $dimension = $this->dimension; - $units = []; - - $this->normalizeUnits($dimension, $units, 'in'); - - $dimension = round($dimension, static::$precision); - $units = array_filter($units, function ($unitSize) { - return $unitSize; - }); + if (is_nan($dimension)) { + return 'NaN'; } - $unitSize = array_sum($units); - - if ($compiler && ($unitSize > 1 || $unitSize < 0 || count($units) > 1)) { - $compiler->throwError((string) $dimension . $this->unitStr() . " isn't a valid CSS value."); + if ($dimension === INF) { + return 'Infinity'; } - reset($units); - $unit = key($units); - $dimension = number_format($dimension, static::$precision, '.', ''); + if ($dimension === -INF) { + return '-Infinity'; + } - return (static::$precision ? rtrim(rtrim($dimension, '0'), '.') : $dimension) . $unit; + if ($compiler) { + $unit = $this->unitStr(); + } elseif (isset($this->numeratorUnits[0])) { + $unit = $this->numeratorUnits[0]; + } else { + $unit = ''; + } + + $dimension = number_format($dimension, self::PRECISION, '.', ''); + + return rtrim(rtrim($dimension, '0'), '.') . $unit; } /** @@ -305,26 +576,229 @@ class Number extends Node implements \ArrayAccess } /** - * Normalize units + * @param Number $other + * @param callable $operation * - * @param integer|float $dimension - * @param array $units - * @param string $baseUnit + * @return Number + * + * @phpstan-param callable(int|float, int|float): (int|float) $operation */ - private function normalizeUnits(&$dimension, &$units, $baseUnit = 'in') + private function coerceNumber(Number $other, $operation) { - $dimension = $this->dimension; - $units = []; + $result = $this->coerceUnits($other, $operation); - foreach ($this->units as $unit => $exp) { - if (isset(static::$unitTable[$baseUnit][$unit])) { - $factor = pow(static::$unitTable[$baseUnit][$unit], $exp); + if (!$this->unitless()) { + return new Number($result, $this->numeratorUnits, $this->denominatorUnits); + } - $unit = $baseUnit; - $dimension /= $factor; + return new Number($result, $other->numeratorUnits, $other->denominatorUnits); + } + + /** + * @param Number $other + * @param callable $operation + * + * @return mixed + * + * @phpstan-template T + * @phpstan-param callable(int|float, int|float): T $operation + * @phpstan-return T + */ + private function coerceUnits(Number $other, $operation) + { + if (!$this->unitless()) { + $num1 = $this->dimension; + $num2 = $other->valueInUnits($this->numeratorUnits, $this->denominatorUnits); + } else { + $num1 = $this->valueInUnits($other->numeratorUnits, $other->denominatorUnits); + $num2 = $other->dimension; + } + + return \call_user_func($operation, $num1, $num2); + } + + /** + * @param string[] $numeratorUnits + * @param string[] $denominatorUnits + * + * @return int|float + * + * @phpstan-param list $numeratorUnits + * @phpstan-param list $denominatorUnits + * + * @throws SassScriptException if this number's units are not compatible with $numeratorUnits and $denominatorUnits + */ + private function valueInUnits(array $numeratorUnits, array $denominatorUnits) + { + if ( + $this->unitless() + || (\count($numeratorUnits) === 0 && \count($denominatorUnits) === 0) + || ($this->numeratorUnits === $numeratorUnits && $this->denominatorUnits === $denominatorUnits) + ) { + return $this->dimension; + } + + $value = $this->dimension; + $oldNumerators = $this->numeratorUnits; + + foreach ($numeratorUnits as $newNumerator) { + foreach ($oldNumerators as $key => $oldNumerator) { + $conversionFactor = self::getConversionFactor($newNumerator, $oldNumerator); + + if (\is_null($conversionFactor)) { + continue; + } + + $value *= $conversionFactor; + unset($oldNumerators[$key]); + continue 2; } - $units[$unit] = $exp + (isset($units[$unit]) ? $units[$unit] : 0); + throw new SassScriptException(sprintf( + 'Incompatible units %s and %s.', + self::getUnitString($this->numeratorUnits, $this->denominatorUnits), + self::getUnitString($numeratorUnits, $denominatorUnits) + )); } + + $oldDenominators = $this->denominatorUnits; + + foreach ($denominatorUnits as $newDenominator) { + foreach ($oldDenominators as $key => $oldDenominator) { + $conversionFactor = self::getConversionFactor($newDenominator, $oldDenominator); + + if (\is_null($conversionFactor)) { + continue; + } + + $value /= $conversionFactor; + unset($oldDenominators[$key]); + continue 2; + } + + throw new SassScriptException(sprintf( + 'Incompatible units %s and %s.', + self::getUnitString($this->numeratorUnits, $this->denominatorUnits), + self::getUnitString($numeratorUnits, $denominatorUnits) + )); + } + + if (\count($oldNumerators) || \count($oldDenominators)) { + throw new SassScriptException(sprintf( + 'Incompatible units %s and %s.', + self::getUnitString($this->numeratorUnits, $this->denominatorUnits), + self::getUnitString($numeratorUnits, $denominatorUnits) + )); + } + + return $value; + } + + /** + * @param int|float $value + * @param string[] $numerators1 + * @param string[] $denominators1 + * @param string[] $numerators2 + * @param string[] $denominators2 + * + * @return Number + * + * @phpstan-param list $numerators1 + * @phpstan-param list $denominators1 + * @phpstan-param list $numerators2 + * @phpstan-param list $denominators2 + */ + private function multiplyUnits($value, array $numerators1, array $denominators1, array $numerators2, array $denominators2) + { + $newNumerators = array(); + + foreach ($numerators1 as $numerator) { + foreach ($denominators2 as $key => $denominator) { + $conversionFactor = self::getConversionFactor($numerator, $denominator); + + if (\is_null($conversionFactor)) { + continue; + } + + $value /= $conversionFactor; + unset($denominators2[$key]); + continue 2; + } + + $newNumerators[] = $numerator; + } + + foreach ($numerators2 as $numerator) { + foreach ($denominators1 as $key => $denominator) { + $conversionFactor = self::getConversionFactor($numerator, $denominator); + + if (\is_null($conversionFactor)) { + continue; + } + + $value /= $conversionFactor; + unset($denominators1[$key]); + continue 2; + } + + $newNumerators[] = $numerator; + } + + $newDenominators = array_values(array_merge($denominators1, $denominators2)); + + return new Number($value, $newNumerators, $newDenominators); + } + + /** + * Returns the number of [unit1]s per [unit2]. + * + * Equivalently, `1unit1 * conversionFactor(unit1, unit2) = 1unit2`. + * + * @param string $unit1 + * @param string $unit2 + * + * @return float|int|null + */ + private static function getConversionFactor($unit1, $unit2) + { + if ($unit1 === $unit2) { + return 1; + } + + foreach (static::$unitTable as $unitVariants) { + if (isset($unitVariants[$unit1]) && isset($unitVariants[$unit2])) { + return $unitVariants[$unit1] / $unitVariants[$unit2]; + } + } + + return null; + } + + /** + * Returns unit(s) as the product of numerator units divided by the product of denominator units + * + * @param string[] $numerators + * @param string[] $denominators + * + * @phpstan-param list $numerators + * @phpstan-param list $denominators + * + * @return string + */ + private static function getUnitString(array $numerators, array $denominators) + { + if (!\count($numerators)) { + if (\count($denominators) === 0) { + return 'no units'; + } + + if (\count($denominators) === 1) { + return $denominators[0] . '^-1'; + } + + return '(' . implode('*', $denominators) . ')^-1'; + } + + return implode('*', $numerators) . (\count($denominators) ? '/' . implode('*', $denominators) : ''); } } diff --git a/lib/scssphp/scssphp/src/OutputStyle.php b/lib/scssphp/scssphp/src/OutputStyle.php new file mode 100644 index 000000000..c284639c1 --- /dev/null +++ b/lib/scssphp/scssphp/src/OutputStyle.php @@ -0,0 +1,9 @@ + + * + * @internal */ class Parser { @@ -30,7 +43,7 @@ class Parser const SOURCE_COLUMN = -3; /** - * @var array + * @var array */ protected static $precedence = [ '=' => 0, @@ -38,7 +51,6 @@ class Parser 'and' => 2, '==' => 3, '!=' => 3, - '<=>' => 3, '<=' => 4, '>=' => 4, '<' => 4, @@ -50,49 +62,97 @@ class Parser '%' => 6, ]; + /** + * @var string + */ protected static $commentPattern; + /** + * @var string + */ protected static $operatorPattern; + /** + * @var string + */ protected static $whitePattern; + /** + * @var Cache|null + */ protected $cache; private $sourceName; private $sourceIndex; + /** + * @var array + */ private $sourcePositions; - private $charset; + /** + * The current offset in the buffer + * + * @var int + */ private $count; + /** + * @var Block|null + */ private $env; + /** + * @var bool + */ private $inParens; + /** + * @var bool + */ private $eatWhiteDefault; + /** + * @var bool + */ private $discardComments; + private $allowVars; + /** + * @var string + */ private $buffer; private $utf8; + /** + * @var string|null + */ private $encoding; private $patternModifiers; private $commentsSeen; + private $cssOnly; + + /** + * @var LoggerInterface + */ + private $logger; + /** * Constructor * * @api * - * @param string $sourceName - * @param integer $sourceIndex - * @param string $encoding - * @param \ScssPhp\ScssPhp\Cache $cache + * @param string|null $sourceName + * @param int $sourceIndex + * @param string|null $encoding + * @param Cache|null $cache + * @param bool $cssOnly + * @param LoggerInterface|null $logger */ - public function __construct($sourceName, $sourceIndex = 0, $encoding = 'utf-8', $cache = null) + public function __construct($sourceName, $sourceIndex = 0, $encoding = 'utf-8', Cache $cache = null, $cssOnly = false, LoggerInterface $logger = null) { $this->sourceName = $sourceName ?: '(stdin)'; $this->sourceIndex = $sourceIndex; - $this->charset = null; $this->utf8 = ! $encoding || strtolower($encoding) === 'utf-8'; $this->patternModifiers = $this->utf8 ? 'Aisu' : 'Ais'; $this->commentsSeen = []; - $this->discardComments = false; + $this->allowVars = true; + $this->cssOnly = $cssOnly; + $this->logger = $logger ?: new QuietLogger(); if (empty(static::$operatorPattern)) { - static::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=\>|\<\=?|and|or)'; + static::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=?|and|or)'; $commentSingle = '\/\/'; $commentMultiLeft = '\/\*'; @@ -104,9 +164,7 @@ class Parser : '/' . $commentSingle . '[^\n]*\s*|(' . static::$commentPattern . ')\s*|\s+/AisS'; } - if ($cache) { - $this->cache = $cache; - } + $this->cache = $cache; } /** @@ -128,9 +186,32 @@ class Parser * * @param string $msg * - * @throws \ScssPhp\ScssPhp\Exception\ParserException + * @phpstan-return never-return + * + * @throws ParserException + * + * @deprecated use "parseError" and throw the exception in the caller instead. */ public function throwParseError($msg = 'parse error') + { + @trigger_error( + 'The method "throwParseError" is deprecated. Use "parseError" and throw the exception in the caller instead', + E_USER_DEPRECATED + ); + + throw $this->parseError($msg); + } + + /** + * Creates a parser error + * + * @api + * + * @param string $msg + * + * @return ParserException + */ + public function parseError($msg = 'parse error') { list($line, $column) = $this->getSourcePosition($this->count); @@ -138,11 +219,21 @@ class Parser ? "line: $line, column: $column" : "$this->sourceName on line $line, at column $column"; - if ($this->peek("(.*?)(\n|$)", $m, $this->count)) { - throw new ParserException("$msg: failed at `$m[1]` $loc"); + if ($this->peek('(.*?)(\n|$)', $m, $this->count)) { + $this->restoreEncoding(); + + $e = new ParserException("$msg: failed at `$m[1]` $loc"); + $e->setSourcePosition([$this->sourceName, $line, $column]); + + return $e; } - throw new ParserException("$msg: $loc"); + $this->restoreEncoding(); + + $e = new ParserException("$msg: $loc"); + $e->setSourcePosition([$this->sourceName, $line, $column]); + + return $e; } /** @@ -152,19 +243,18 @@ class Parser * * @param string $buffer * - * @return \ScssPhp\ScssPhp\Block + * @return Block */ public function parse($buffer) { if ($this->cache) { - $cacheKey = $this->sourceName . ":" . md5($buffer); + $cacheKey = $this->sourceName . ':' . md5($buffer); $parseOptions = [ - 'charset' => $this->charset, 'utf8' => $this->utf8, ]; - $v = $this->cache->getCache("parse", $cacheKey, $parseOptions); + $v = $this->cache->getCache('parse', $cacheKey, $parseOptions); - if (! is_null($v)) { + if (! \is_null($v)) { return $v; } } @@ -192,22 +282,19 @@ class Parser ; } - if ($this->count !== strlen($this->buffer)) { - $this->throwParseError(); + if ($this->count !== \strlen($this->buffer)) { + throw $this->parseError(); } if (! empty($this->env->parent)) { - $this->throwParseError('unclosed block'); - } - - if ($this->charset) { - array_unshift($this->env->children, $this->charset); + throw $this->parseError('unclosed block'); } $this->restoreEncoding(); + assert($this->env !== null); if ($this->cache) { - $this->cache->setCache("parse", $cacheKey, $this->env, $parseOptions); + $this->cache->setCache('parse', $cacheKey, $this->env, $parseOptions); } return $this->env; @@ -221,7 +308,7 @@ class Parser * @param string $buffer * @param string|array $out * - * @return boolean + * @return bool */ public function parseValue($buffer, &$out) { @@ -232,6 +319,7 @@ class Parser $this->buffer = (string) $buffer; $this->saveEncoding(); + $this->extractLineNumbers($this->buffer); $list = $this->valueList($out); @@ -247,10 +335,11 @@ class Parser * * @param string $buffer * @param string|array $out + * @param bool $shouldValidate * - * @return boolean + * @return bool */ - public function parseSelector($buffer, &$out) + public function parseSelector($buffer, &$out, $shouldValidate = true) { $this->count = 0; $this->env = null; @@ -259,11 +348,21 @@ class Parser $this->buffer = (string) $buffer; $this->saveEncoding(); + $this->extractLineNumbers($this->buffer); + + // discard space/comments at the start + $this->discardComments = true; + $this->whitespace(); + $this->discardComments = false; $selector = $this->selectors($out); $this->restoreEncoding(); + if ($shouldValidate && $this->count !== strlen($buffer)) { + throw $this->parseError("`" . substr($buffer, $this->count) . "` is not a valid Selector in `$buffer`"); + } + return $selector; } @@ -272,10 +371,10 @@ class Parser * * @api * - * @param string $buffer - * @param string|array $out + * @param string $buffer + * @param array $out * - * @return boolean + * @return bool */ public function parseMediaQueryList($buffer, &$out) { @@ -286,6 +385,7 @@ class Parser $this->buffer = (string) $buffer; $this->saveEncoding(); + $this->extractLineNumbers($this->buffer); $isMediaQuery = $this->mediaQueryList($out); @@ -331,7 +431,7 @@ class Parser * position into $s. Then if a chain fails, use $this->seek($s) to * go back where we started. * - * @return boolean + * @return bool */ protected function parseChunk() { @@ -339,15 +439,19 @@ class Parser // the directives if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] === '@') { - if ($this->literal('@at-root', 8) && + if ( + $this->literal('@at-root', 8) && ($this->selectors($selector) || true) && ($this->map($with) || true) && - (($this->matchChar('(') - && $this->interpolation($with) - && $this->matchChar(')')) || true) && + (($this->matchChar('(') && + $this->interpolation($with) && + $this->matchChar(')')) || true) && $this->matchChar('{', false) ) { - $atRoot = $this->pushSpecialBlock(Type::T_AT_ROOT, $s); + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + + $atRoot = new AtRootBlock(); + $this->registerPushedBlock($atRoot, $s); $atRoot->selector = $selector; $atRoot->with = $with; @@ -356,8 +460,13 @@ class Parser $this->seek($s); - if ($this->literal('@media', 6) && $this->mediaQueryList($mediaQueryList) && $this->matchChar('{', false)) { - $media = $this->pushSpecialBlock(Type::T_MEDIA, $s); + if ( + $this->literal('@media', 6) && + $this->mediaQueryList($mediaQueryList) && + $this->matchChar('{', false) + ) { + $media = new MediaBlock(); + $this->registerPushedBlock($media, $s); $media->queryList = $mediaQueryList[2]; return true; @@ -365,12 +474,16 @@ class Parser $this->seek($s); - if ($this->literal('@mixin', 6) && + if ( + $this->literal('@mixin', 6) && $this->keyword($mixinName) && ($this->argumentDef($args) || true) && $this->matchChar('{', false) ) { - $mixin = $this->pushSpecialBlock(Type::T_MIXIN, $s); + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + + $mixin = new CallableBlock(Type::T_MIXIN); + $this->registerPushedBlock($mixin, $s); $mixin->name = $mixinName; $mixin->args = $args; @@ -379,17 +492,20 @@ class Parser $this->seek($s); - if ($this->literal('@include', 8) && - $this->keyword($mixinName) && - ($this->matchChar('(') && + if ( + ($this->literal('@include', 8) && + $this->keyword($mixinName) && + ($this->matchChar('(') && ($this->argValues($argValues) || true) && $this->matchChar(')') || true) && - ($this->end() || - ($this->literal('using', 5) && - $this->argumentDef($argUsing) && - ($this->end() || $this->matchChar('{') && $hasBlock = true)) || - $this->matchChar('{') && $hasBlock = true) + ($this->end()) || + ($this->literal('using', 5) && + $this->argumentDef($argUsing) && + ($this->end() || $this->matchChar('{') && $hasBlock = true)) || + $this->matchChar('{') && $hasBlock = true) ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + $child = [ Type::T_INCLUDE, $mixinName, @@ -399,7 +515,8 @@ class Parser ]; if (! empty($hasBlock)) { - $include = $this->pushSpecialBlock(Type::T_INCLUDE, $s); + $include = new ContentBlock(); + $this->registerPushedBlock($include, $s); $include->child = $child; } else { $this->append($child, $s); @@ -410,10 +527,17 @@ class Parser $this->seek($s); - if ($this->literal('@scssphp-import-once', 20) && + if ( + $this->literal('@scssphp-import-once', 20) && $this->valueList($importPath) && $this->end() ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + + list($line, $column) = $this->getSourcePosition($s); + $file = $this->sourceName; + $this->logger->warn("The \"@scssphp-import-once\" directive is deprecated and will be removed in ScssPhp 2.0, in \"$file\", line $line, column $column.", true); + $this->append([Type::T_SCSSPHP_IMPORT_ONCE, $importPath], $s); return true; @@ -421,10 +545,18 @@ class Parser $this->seek($s); - if ($this->literal('@import', 7) && + if ( + $this->literal('@import', 7) && $this->valueList($importPath) && + $importPath[0] !== Type::T_FUNCTION_CALL && $this->end() ) { + if ($this->cssOnly) { + $this->assertPlainCssValid([Type::T_IMPORT, $importPath], $s); + $this->append([Type::T_COMMENT, rtrim(substr($this->buffer, $s, $this->count - $s))]); + return true; + } + $this->append([Type::T_IMPORT, $importPath], $s); return true; @@ -432,10 +564,17 @@ class Parser $this->seek($s); - if ($this->literal('@import', 7) && + if ( + $this->literal('@import', 7) && $this->url($importPath) && $this->end() ) { + if ($this->cssOnly) { + $this->assertPlainCssValid([Type::T_IMPORT, $importPath], $s); + $this->append([Type::T_COMMENT, rtrim(substr($this->buffer, $s, $this->count - $s))]); + return true; + } + $this->append([Type::T_IMPORT, $importPath], $s); return true; @@ -443,10 +582,13 @@ class Parser $this->seek($s); - if ($this->literal('@extend', 7) && + if ( + $this->literal('@extend', 7) && $this->selectors($selectors) && $this->end() ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + // check for '!flag' $optional = $this->stripOptionalFlag($selectors); $this->append([Type::T_EXTEND, $selectors, $optional], $s); @@ -456,12 +598,16 @@ class Parser $this->seek($s); - if ($this->literal('@function', 9) && + if ( + $this->literal('@function', 9) && $this->keyword($fnName) && $this->argumentDef($args) && $this->matchChar('{', false) ) { - $func = $this->pushSpecialBlock(Type::T_FUNCTION, $s); + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + + $func = new CallableBlock(Type::T_FUNCTION); + $this->registerPushedBlock($func, $s); $func->name = $fnName; $func->args = $args; @@ -470,23 +616,13 @@ class Parser $this->seek($s); - if ($this->literal('@break', 6) && $this->end()) { - $this->append([Type::T_BREAK], $s); + if ( + $this->literal('@return', 7) && + ($this->valueList($retVal) || true) && + $this->end() + ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - return true; - } - - $this->seek($s); - - if ($this->literal('@continue', 9) && $this->end()) { - $this->append([Type::T_CONTINUE], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@return', 7) && ($this->valueList($retVal) || true) && $this->end()) { $this->append([Type::T_RETURN, isset($retVal) ? $retVal : [Type::T_NULL]], $s); return true; @@ -494,13 +630,17 @@ class Parser $this->seek($s); - if ($this->literal('@each', 5) && + if ( + $this->literal('@each', 5) && $this->genericList($varNames, 'variable', ',', false) && $this->literal('in', 2) && $this->valueList($list) && $this->matchChar('{', false) ) { - $each = $this->pushSpecialBlock(Type::T_EACH, $s); + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + + $each = new EachBlock(); + $this->registerPushedBlock($each, $s); foreach ($varNames[2] as $varName) { $each->vars[] = $varName[1]; @@ -513,11 +653,24 @@ class Parser $this->seek($s); - if ($this->literal('@while', 6) && + if ( + $this->literal('@while', 6) && $this->expression($cond) && $this->matchChar('{', false) ) { - $while = $this->pushSpecialBlock(Type::T_WHILE, $s); + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + + while ( + $cond[0] === Type::T_LIST && + ! empty($cond['enclosing']) && + $cond['enclosing'] === 'parent' && + \count($cond[2]) == 1 + ) { + $cond = reset($cond[2]); + } + + $while = new WhileBlock(); + $this->registerPushedBlock($while, $s); $while->cond = $cond; return true; @@ -525,7 +678,8 @@ class Parser $this->seek($s); - if ($this->literal('@for', 4) && + if ( + $this->literal('@for', 4) && $this->variable($varName) && $this->literal('from', 4) && $this->expression($start) && @@ -534,7 +688,10 @@ class Parser $this->expression($end) && $this->matchChar('{', false) ) { - $for = $this->pushSpecialBlock(Type::T_FOR, $s); + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + + $for = new ForBlock(); + $this->registerPushedBlock($for, $s); $for->var = $varName[1]; $for->start = $start; $for->end = $end; @@ -545,14 +702,24 @@ class Parser $this->seek($s); - if ($this->literal('@if', 3) && $this->valueList($cond) && $this->matchChar('{', false)) { - $if = $this->pushSpecialBlock(Type::T_IF, $s); - while ($cond[0] === Type::T_LIST - && !empty($cond['enclosing']) - && $cond['enclosing'] === 'parent' - && count($cond[2]) == 1) { + if ( + $this->literal('@if', 3) && + $this->functionCallArgumentsList($cond, false, '{', false) + ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + + $if = new IfBlock(); + $this->registerPushedBlock($if, $s); + + while ( + $cond[0] === Type::T_LIST && + ! empty($cond['enclosing']) && + $cond['enclosing'] === 'parent' && + \count($cond[2]) == 1 + ) { $cond = reset($cond[2]); } + $if->cond = $cond; $if->cases = []; @@ -561,10 +728,12 @@ class Parser $this->seek($s); - if ($this->literal('@debug', 6) && - $this->valueList($value) && - $this->end() + if ( + $this->literal('@debug', 6) && + $this->functionCallArgumentsList($value, false) ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + $this->append([Type::T_DEBUG, $value], $s); return true; @@ -572,10 +741,12 @@ class Parser $this->seek($s); - if ($this->literal('@warn', 5) && - $this->valueList($value) && - $this->end() + if ( + $this->literal('@warn', 5) && + $this->functionCallArgumentsList($value, false) ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + $this->append([Type::T_WARN, $value], $s); return true; @@ -583,10 +754,12 @@ class Parser $this->seek($s); - if ($this->literal('@error', 6) && - $this->valueList($value) && - $this->end() + if ( + $this->literal('@error', 6) && + $this->functionCallArgumentsList($value, false) ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + $this->append([Type::T_ERROR, $value], $s); return true; @@ -594,14 +767,16 @@ class Parser $this->seek($s); - #if ($this->literal('@content', 8)) - - if ($this->literal('@content', 8) && + if ( + $this->literal('@content', 8) && ($this->end() || $this->matchChar('(') && - $this->argValues($argContent) && - $this->matchChar(')') && - $this->end())) { + $this->argValues($argContent) && + $this->matchChar(')') && + $this->end()) + ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + $this->append([Type::T_MIXIN_CONTENT, isset($argContent) ? $argContent : null], $s); return true; @@ -613,17 +788,21 @@ class Parser if (isset($last) && $last[0] === Type::T_IF) { list(, $if) = $last; + assert($if instanceof IfBlock); if ($this->literal('@else', 5)) { if ($this->matchChar('{', false)) { - $else = $this->pushSpecialBlock(Type::T_ELSE, $s); - } elseif ($this->literal('if', 2) && $this->valueList($cond) && $this->matchChar('{', false)) { - $else = $this->pushSpecialBlock(Type::T_ELSEIF, $s); + $else = new ElseBlock(); + } elseif ( + $this->literal('if', 2) && + $this->functionCallArgumentsList($cond, false, '{', false) + ) { + $else = new ElseifBlock(); $else->cond = $cond; } if (isset($else)) { - $else->dontAppend = true; + $this->registerPushedBlock($else, $s); $if->cases[] = $else; return true; @@ -634,32 +813,23 @@ class Parser } // only retain the first @charset directive encountered - if ($this->literal('@charset', 8) && + if ( + $this->literal('@charset', 8) && $this->valueList($charset) && $this->end() ) { - if (! isset($this->charset)) { - $statement = [Type::T_CHARSET, $charset]; - - list($line, $column) = $this->getSourcePosition($s); - - $statement[static::SOURCE_LINE] = $line; - $statement[static::SOURCE_COLUMN] = $column; - $statement[static::SOURCE_INDEX] = $this->sourceIndex; - - $this->charset = $statement; - } - return true; } $this->seek($s); - if ($this->literal('@supports', 9) && - ($t1=$this->supportsQuery($supportQuery)) && - ($t2=$this->matchChar('{', false)) + if ( + $this->literal('@supports', 9) && + ($t1 = $this->supportsQuery($supportQuery)) && + ($t2 = $this->matchChar('{', false)) ) { - $directive = $this->pushSpecialBlock(Type::T_DIRECTIVE, $s); + $directive = new DirectiveBlock(); + $this->registerPushedBlock($directive, $s); $directive->name = 'supports'; $directive->value = $supportQuery; @@ -669,19 +839,26 @@ class Parser $this->seek($s); // doesn't match built in directive, do generic one - if ($this->matchChar('@', false) && - $this->keyword($dirName) && - ($this->variable($dirValue) || $this->openString('{', $dirValue) || true) && - $this->matchChar('{', false) + if ( + $this->matchChar('@', false) && + $this->mixedKeyword($dirName) && + $this->directiveValue($dirValue, '{') ) { - if ($dirName === 'media') { - $directive = $this->pushSpecialBlock(Type::T_MEDIA, $s); + if (count($dirName) === 1 && is_string(reset($dirName))) { + $dirName = reset($dirName); } else { - $directive = $this->pushSpecialBlock(Type::T_DIRECTIVE, $s); + $dirName = [Type::T_STRING, '', $dirName]; + } + if ($dirName === 'media') { + $directive = new MediaBlock(); + } else { + $directive = new DirectiveBlock(); $directive->name = $dirName; } + $this->registerPushedBlock($directive, $s); if (isset($dirValue)) { + ! $this->cssOnly || ($dirValue = $this->assertPlainCssValid($dirValue)); $directive->value = $dirValue; } @@ -691,12 +868,38 @@ class Parser $this->seek($s); // maybe it's a generic blockless directive - if ($this->matchChar('@', false) && - $this->keyword($dirName) && - $this->valueList($dirValue) && - $this->end() + if ( + $this->matchChar('@', false) && + $this->mixedKeyword($dirName) && + ! $this->isKnownGenericDirective($dirName) && + ($this->end(false) || ($this->directiveValue($dirValue, '') && $this->end(false))) ) { - $this->append([Type::T_DIRECTIVE, [$dirName, $dirValue]], $s); + if (\count($dirName) === 1 && \is_string(\reset($dirName))) { + $dirName = \reset($dirName); + } else { + $dirName = [Type::T_STRING, '', $dirName]; + } + if ( + ! empty($this->env->parent) && + $this->env->type && + ! \in_array($this->env->type, [Type::T_DIRECTIVE, Type::T_MEDIA]) + ) { + $plain = \trim(\substr($this->buffer, $s, $this->count - $s)); + throw $this->parseError( + "Unknown directive `{$plain}` not allowed in `" . $this->env->type . "` block" + ); + } + // blockless directives with a blank line after keeps their blank lines after + // sass-spec compliance purpose + $s = $this->count; + $hasBlankLine = false; + if ($this->match('\s*?\n\s*\n', $out, false)) { + $hasBlankLine = true; + $this->seek($s); + } + $isNotRoot = ! empty($this->env->parent); + $this->append([Type::T_DIRECTIVE, [$dirName, $dirValue, $hasBlankLine, $isNotRoot]], $s); + $this->whitespace(); return true; } @@ -706,9 +909,60 @@ class Parser return false; } + $inCssSelector = null; + if ($this->cssOnly) { + $inCssSelector = (! empty($this->env->parent) && + ! in_array($this->env->type, [Type::T_DIRECTIVE, Type::T_MEDIA])); + } + // custom properties : right part is static + if (($this->customProperty($name) ) && $this->matchChar(':', false)) { + $start = $this->count; + + // but can be complex and finish with ; or } + foreach ([';','}'] as $ending) { + if ( + $this->openString($ending, $stringValue, '(', ')', false) && + $this->end() + ) { + $end = $this->count; + $value = $stringValue; + + // check if we have only a partial value due to nested [] or { } to take in account + $nestingPairs = [['[', ']'], ['{', '}']]; + + foreach ($nestingPairs as $nestingPair) { + $p = strpos($this->buffer, $nestingPair[0], $start); + + if ($p && $p < $end) { + $this->seek($start); + + if ( + $this->openString($ending, $stringValue, $nestingPair[0], $nestingPair[1], false) && + $this->end() && + $this->count > $end + ) { + $end = $this->count; + $value = $stringValue; + } + } + } + + $this->seek($end); + $this->append([Type::T_CUSTOM_PROPERTY, $name, $value], $s); + + return true; + } + } + + // TODO: output an error here if nothing found according to sass spec + } + + $this->seek($s); + // property shortcut // captures most properties before having to parse a selector - if ($this->keyword($name, false) && + if ( + $this->keyword($name, false) && $this->literal(': ', 2) && $this->valueList($value) && $this->end() @@ -722,11 +976,14 @@ class Parser $this->seek($s); // variable assigns - if ($this->variable($name) && + if ( + $this->variable($name) && $this->matchChar(':') && $this->valueList($value) && $this->end() ) { + ! $this->cssOnly || $this->assertPlainCssValid(false, $s); + // check for '!flag' $assignmentFlags = $this->stripAssignmentFlags($value); $this->append([Type::T_ASSIGN, $name, $value, $assignmentFlags], $s); @@ -736,13 +993,13 @@ class Parser $this->seek($s); - // misc - if ($this->literal('-->', 3)) { - return true; - } - // opening css block - if ($this->selectors($selectors) && $this->matchChar('{', false)) { + if ( + $this->selectors($selectors) && + $this->matchChar('{', false) + ) { + ! $this->cssOnly || ! $inCssSelector || $this->assertPlainCssValid(false); + $this->pushBlock($selectors, $s); if ($this->eatWhiteDefault) { @@ -756,12 +1013,15 @@ class Parser $this->seek($s); // property assign, or nested assign - if ($this->propertyName($name) && $this->matchChar(':')) { + if ( + $this->propertyName($name) && + $this->matchChar(':') + ) { $foundSomething = false; if ($this->valueList($value)) { if (empty($this->env->parent)) { - $this->throwParseError('expected "{"'); + throw $this->parseError('expected "{"'); } $this->append([Type::T_ASSIGN, $name, $value], $s); @@ -769,7 +1029,10 @@ class Parser } if ($this->matchChar('{', false)) { - $propBlock = $this->pushSpecialBlock(Type::T_NESTED_PROPERTY, $s); + ! $this->cssOnly || $this->assertPlainCssValid(false); + + $propBlock = new NestedPropertyBlock(); + $this->registerPushedBlock($propBlock, $s); $propBlock->prefix = $name; $propBlock->hasValue = $foundSomething; @@ -790,17 +1053,20 @@ class Parser $block = $this->popBlock(); if (! isset($block->type) || $block->type !== Type::T_IF) { + assert($this->env !== null); + if ($this->env->parent) { $this->append(null); // collect comments before next statement if needed } } - if (isset($block->type) && $block->type === Type::T_INCLUDE) { + if ($block instanceof ContentBlock) { $include = $block->child; + assert(\is_array($include)); unset($block->child); $include[3] = $block; $this->append($include, $s); - } elseif (empty($block->dontAppend)) { + } elseif (!$block instanceof ElseBlock && !$block instanceof ElseifBlock) { $type = isset($block->type) ? $block->type : Type::T_BLOCK; $this->append([$type, $block], $s); } @@ -808,6 +1074,7 @@ class Parser // collect comments just after the block closing if needed if ($this->eatWhiteDefault) { $this->whitespace(); + assert($this->env !== null); if ($this->env->comments) { $this->append(null); @@ -818,9 +1085,7 @@ class Parser } // extra stuff - if ($this->matchChar(';') || - $this->literal('