diff --git a/.gitignore b/.gitignore index 4d6216b34..d3d699cd0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,5 @@ /laminas-mkdoc-theme/ /phpunit.xml /vendor/ -.phpunit.result.cache +.phpunit.cache .phpcs-cache diff --git a/README.md b/README.md index 6d735e277..3803c8e51 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,19 @@ [![Build Status](https://github.com/laminas/laminas-view/workflows/Continuous%20Integration/badge.svg)](https://github.com/laminas/laminas-view/actions?query=workflow%3A"Continuous+Integration") > ## πŸ‡·πŸ‡Ί Русским Π³Ρ€Π°ΠΆΠ΄Π°Π½Π°ΠΌ -> +> > ΠœΡ‹, участники Laminas, Ρ€ΠΎΠ΄ΠΈΠ»ΠΈΡΡŒ ΠΈ ΠΆΠΈΠ²Π΅ΠΌ Π² Ρ€Π°Π·Π½Ρ‹Ρ… странах. Π£ ΠΌΠ½ΠΎΠ³ΠΈΡ… ΠΈΠ· нас Π΅ΡΡ‚ΡŒ Π΄Ρ€ΡƒΠ·ΡŒΡ, родствСнники ΠΈ ΠΊΠΎΠ»Π»Π΅Π³ΠΈ ΠΊΠ°ΠΊ Π² России, Ρ‚Π°ΠΊ ΠΈ Π² Π£ΠΊΡ€Π°ΠΈΠ½Π΅. НСкоторыС ΠΈΠ· нас Ρ€ΠΎΠ΄ΠΈΠ»ΠΈΡΡŒ Π² России. НСкоторыС ΠΈΠ· нас ΠΆΠΈΠ²ΡƒΡ‚ Π² России. Π£ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π±Π°Π±ΡƒΡˆΠΊΠΈ ΠΈ Π΄Π΅Π΄ΡƒΡˆΠΊΠΈ ΡΡ€Π°ΠΆΠ°Π»ΠΈΡΡŒ с Ρ„Π°ΡˆΠΈΡΡ‚Π°ΠΌΠΈ Π²ΠΎ Π’Ρ‚ΠΎΡ€ΠΎΠΉ ΠΌΠΈΡ€ΠΎΠ²ΠΎΠΉ Π²ΠΎΠΉΠ½Π΅. Π—Π΄Π΅ΡΡŒ Π½ΠΈΠΊΡ‚ΠΎ Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Ρ„Π°ΡˆΠΈΠ·ΠΌ. -> +> > Π£ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· нас Π΅ΡΡ‚ΡŒ украинская родствСнница, которая спаслась ΠΈΠ· Π΄ΠΎΠΌΠ° вмСстС с сыном. ПоСзд задСрТался ΠΈΠ·-Π·Π° Π±ΠΎΠΌΠ±Π΅ΠΆΠΊΠΈ Π½Π° Π΄ΠΎΡ€ΠΎΠ³Π΅ Π²ΠΏΠ΅Ρ€Π΅Π΄ΠΈ. Π£ нас Π΅ΡΡ‚ΡŒ Π΄Ρ€ΡƒΠ·ΡŒΡ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ прячутся Π² Π±ΠΎΠΌΠ±ΠΎΡƒΠ±Π΅ΠΆΠΈΡ‰Π°Ρ…. ΠœΡ‹ с Ρ‚Ρ€Π΅Π²ΠΎΠ³ΠΎΠΉ ΠΆΠ΄Π΅ΠΌ вСсточки ΠΎΡ‚ Π½ΠΈΡ… послС Π²ΠΎΠ·Π΄ΡƒΡˆΠ½Ρ‹Ρ… Π½Π°Π»Π΅Ρ‚ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ бСспорядочно наносят ΡƒΠ΄Π°Ρ€Ρ‹ ΠΈ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ ΠΏΠΎ Π±ΠΎΠ»ΡŒΠ½ΠΈΡ†Π°ΠΌ, школам, дСтским садам ΠΈ Π΄ΠΎΠΌΠ°ΠΌ. ΠœΡ‹ Π½Π΅ Π±Π΅Ρ€Π΅ΠΌ это ΠΈΠ· ΠΊΠ°ΠΊΠΈΡ…-Π»ΠΈΠ±ΠΎ БМИ. ΠœΡ‹ наблюдаСм это Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ. -> +> > Π’Ρ‹ довСряСтС Π½Π°ΠΌ достаточно, Ρ‡Ρ‚ΠΎΠ± ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ наши ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, ΠΈ ΠΌΡ‹ просим вас Π΄ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒΡΡ Π½Π°ΠΌ вновь. ΠœΡ‹ нуТдаСмся Π² ΠΏΠΎΠΌΠΎΡ‰ΠΈ. Π’Ρ‹Ρ…ΠΎΠ΄ΠΈΡ‚Π΅ ΠΈ протСстуйтС ΠΏΡ€ΠΎΡ‚ΠΈΠ² этой бСсполСзной Π²ΠΎΠΉΠ½Ρ‹. ΠžΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚Π΅ ΠΊΡ€ΠΎΠ²ΠΎΠΏΡ€ΠΎΠ»ΠΈΡ‚ΠΈΠ΅. Π‘ΠΊΠ°ΠΆΠΈΡ‚Π΅ "НСт Π²ΠΎΠΉΠ½Π΅!" -> +> > ## πŸ‡ΊπŸ‡Έ To Citizens of Russia -> +> > We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism. -> +> > One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences. -> +> > You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!" laminas-view provides the β€œView” layer of the Laminas MVC system. It is a diff --git a/composer.json b/composer.json index 7edae969c..b646bff3a 100644 --- a/composer.json +++ b/composer.json @@ -49,10 +49,10 @@ "laminas/laminas-mvc-i18n": "^1.7", "laminas/laminas-navigation": "^2.18.1", "laminas/laminas-paginator": "^2.17", - "laminas/laminas-permissions-acl": "^2.14", + "laminas/laminas-permissions-acl": "^2.15", "laminas/laminas-router": "^3.11.1", "laminas/laminas-uri": "^2.10", - "phpunit/phpunit": "^9.6.8", + "phpunit/phpunit": "^10.1.3", "psalm/plugin-phpunit": "^0.18.4", "vimeo/psalm": "^5.12" }, diff --git a/composer.lock b/composer.lock index 5c2c647ee..639e66436 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9e4b0916dfeafce145bdc10f7d156d58", + "content-hash": "6f4f1dcd9aabd89a90c6f0ad6d25cc20", "packages": [ { "name": "laminas/laminas-escaper", @@ -1015,76 +1015,6 @@ }, "time": "2019-12-04T15:06:13+00:00" }, - { - "name": "doctrine/instantiator", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:23:10+00:00" - }, { "name": "felixfbecker/advanced-json-rpc", "version": "v3.2.1", @@ -1249,16 +1179,16 @@ }, { "name": "laminas/laminas-authentication", - "version": "2.13.0", + "version": "2.15.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-authentication.git", - "reference": "12bfb36b8b20052a5fee2ae69b0f12064ce16fa9" + "reference": "9036ae55a84862b16f8631460f90eeea6c19c54e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-authentication/zipball/12bfb36b8b20052a5fee2ae69b0f12064ce16fa9", - "reference": "12bfb36b8b20052a5fee2ae69b0f12064ce16fa9", + "url": "https://api.github.com/repos/laminas/laminas-authentication/zipball/9036ae55a84862b16f8631460f90eeea6c19c54e", + "reference": "9036ae55a84862b16f8631460f90eeea6c19c54e", "shasum": "" }, "require": { @@ -1273,13 +1203,13 @@ "laminas/laminas-crypt": "^2.6.0 || ^3.9.0", "laminas/laminas-db": "^2.15.0", "laminas/laminas-http": "^2.17.0", - "laminas/laminas-ldap": "^2.15.0", + "laminas/laminas-ldap": "^2.16", "laminas/laminas-session": "^2.13.0", "laminas/laminas-uri": "^2.10.0", "laminas/laminas-validator": "^2.26.0", "phpunit/phpunit": "^9.5.25", "psalm/plugin-phpunit": "^0.17.0", - "squizlabs/php_codesniffer": "^3.6.0", + "squizlabs/php_codesniffer": "^3.7.1", "vimeo/psalm": "^4.29.0" }, "suggest": { @@ -1321,7 +1251,7 @@ "type": "community_bridge" } ], - "time": "2022-10-24T08:02:04+00:00" + "time": "2023-07-12T08:21:19+00:00" }, { "name": "laminas/laminas-coding-standard", @@ -2397,16 +2327,16 @@ }, { "name": "laminas/laminas-validator", - "version": "2.31.0", + "version": "2.35.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-validator.git", - "reference": "7dc274aa5afd5e23be0dbea13363e3d66ba5808b" + "reference": "7a4a30f6c526a518ba9af50e037c2f97cb595958" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/7dc274aa5afd5e23be0dbea13363e3d66ba5808b", - "reference": "7dc274aa5afd5e23be0dbea13363e3d66ba5808b", + "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/7a4a30f6c526a518ba9af50e037c2f97cb595958", + "reference": "7a4a30f6c526a518ba9af50e037c2f97cb595958", "shasum": "" }, "require": { @@ -2422,7 +2352,6 @@ "laminas/laminas-coding-standard": "^2.5", "laminas/laminas-db": "^2.18", "laminas/laminas-filter": "^2.32", - "laminas/laminas-http": "^2.18", "laminas/laminas-i18n": "^2.23", "laminas/laminas-session": "^2.16", "laminas/laminas-uri": "^2.10.0", @@ -2430,7 +2359,7 @@ "psalm/plugin-phpunit": "^0.18.4", "psr/http-client": "^1.0.2", "psr/http-factory": "^1.0.2", - "vimeo/psalm": "^5.11" + "vimeo/psalm": "^5.12" }, "suggest": { "laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator", @@ -2478,7 +2407,7 @@ "type": "community_bridge" } ], - "time": "2023-05-19T09:42:26+00:00" + "time": "2023-07-10T07:32:01+00:00" }, { "name": "myclabs/deep-copy", @@ -2592,16 +2521,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.5", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -2642,9 +2571,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2023-05-19T20:20:00+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "phar-io/manifest", @@ -2968,16 +2897,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.26", + "version": "10.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/db1497ec8dd382e82c962f7abbe0320e4882ee4e", + "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e", "shasum": "" }, "require": { @@ -2985,18 +2914,18 @@ "ext-libxml": "*", "ext-xmlwriter": "*", "nikic/php-parser": "^4.15", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -3005,7 +2934,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "10.1-dev" } }, "autoload": { @@ -3033,7 +2962,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.2" }, "funding": [ { @@ -3041,32 +2971,32 @@ "type": "github" } ], - "time": "2023-03-06T12:58:08+00:00" + "time": "2023-05-22T09:04:27+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "5647d65443818959172645e7ed999217360654b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6", + "reference": "5647d65443818959172645e7ed999217360654b6", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -3093,7 +3023,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2" }, "funding": [ { @@ -3101,28 +3032,28 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2023-05-07T09:13:23+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.1.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-pcntl": "*" @@ -3130,7 +3061,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -3156,7 +3087,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, "funding": [ { @@ -3164,32 +3095,32 @@ "type": "github" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2023-02-03T06:56:09+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3215,7 +3146,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0" }, "funding": [ { @@ -3223,32 +3154,32 @@ "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2023-02-03T06:56:46+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -3274,7 +3205,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { @@ -3282,24 +3213,23 @@ "type": "github" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2023-02-03T06:57:52+00:00" }, { "name": "phpunit/phpunit", - "version": "9.6.8", + "version": "10.2.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "17d621b3aff84d0c8b62539e269e87d8d5baa76e" + "reference": "1c17815c129f133f3019cc18e8d0c8622e6d9bcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/17d621b3aff84d0c8b62539e269e87d8d5baa76e", - "reference": "17d621b3aff84d0c8b62539e269e87d8d5baa76e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1c17815c129f133f3019cc18e8d0c8622e6d9bcd", + "reference": "1c17815c129f133f3019cc18e8d0c8622e6d9bcd", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -3309,27 +3239,26 @@ "myclabs/deep-copy": "^1.10.1", "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", - "sebastian/version": "^3.0.2" + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.0", + "sebastian/global-state": "^6.0", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" }, "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -3337,7 +3266,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-main": "10.2-dev" } }, "autoload": { @@ -3369,7 +3298,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.8" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.6" }, "funding": [ { @@ -3385,7 +3314,7 @@ "type": "tidelift" } ], - "time": "2023-05-11T05:14:45+00:00" + "time": "2023-07-17T12:08:28+00:00" }, { "name": "psalm/plugin-phpunit", @@ -3552,28 +3481,28 @@ }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -3596,7 +3525,7 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0" }, "funding": [ { @@ -3604,32 +3533,32 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2023-02-03T06:58:15+00:00" }, { "name": "sebastian/code-unit", - "version": "1.0.8", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -3652,7 +3581,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { @@ -3660,32 +3589,32 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2023-02-03T06:58:43+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3707,7 +3636,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { @@ -3715,34 +3644,36 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2023-02-03T06:59:15+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/72f01e6586e0caf6af81297897bd112eb7e9627c", + "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -3781,7 +3712,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.0" }, "funding": [ { @@ -3789,33 +3720,33 @@ "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2023-02-03T07:07:16+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.2", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6", "shasum": "" }, "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" + "nikic/php-parser": "^4.10", + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3838,7 +3769,7 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0" }, "funding": [ { @@ -3846,33 +3777,33 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2023-02-03T06:59:47+00:00" }, { "name": "sebastian/diff", - "version": "4.0.5", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", + "phpunit/phpunit": "^10.0", "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -3904,7 +3835,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" }, "funding": [ { @@ -3912,27 +3844,27 @@ "type": "github" } ], - "time": "2023-05-07T05:35:17+00:00" + "time": "2023-05-01T07:48:21+00:00" }, { "name": "sebastian/environment", - "version": "5.1.5", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-posix": "*" @@ -3940,7 +3872,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -3959,7 +3891,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -3967,7 +3899,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" }, "funding": [ { @@ -3975,34 +3908,34 @@ "type": "github" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2023-04-11T05:39:26+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.5", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0", + "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -4044,7 +3977,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/exporter/tree/5.0.0" }, "funding": [ { @@ -4052,38 +3985,35 @@ "type": "github" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2023-02-03T07:06:49+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -4108,7 +4038,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1" }, "funding": [ { @@ -4116,33 +4047,33 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-07-19T07:19:23+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.3", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130", + "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130", "shasum": "" }, "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" + "nikic/php-parser": "^4.10", + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -4165,7 +4096,7 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0" }, "funding": [ { @@ -4173,34 +4104,34 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2023-02-03T07:08:02+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.4", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -4222,7 +4153,7 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { @@ -4230,32 +4161,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -4277,7 +4208,7 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { @@ -4285,32 +4216,32 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -4340,7 +4271,7 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" }, "funding": [ { @@ -4348,87 +4279,32 @@ "type": "github" } ], - "time": "2023-02-03T06:07:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2023-02-03T07:05:40+00:00" }, { "name": "sebastian/type", - "version": "3.2.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -4451,7 +4327,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { @@ -4459,29 +4335,29 @@ "type": "github" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -4504,7 +4380,7 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { @@ -4512,7 +4388,7 @@ "type": "github" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { "name": "slevomat/coding-standard", @@ -4577,16 +4453,16 @@ }, { "name": "spatie/array-to-xml", - "version": "3.1.6", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "e210b98957987c755372465be105d32113f339a4" + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/e210b98957987c755372465be105d32113f339a4", - "reference": "e210b98957987c755372465be105d32113f339a4", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f9ab39c808500c347d5a8b6b13310bd5221e39e7", + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7", "shasum": "" }, "require": { @@ -4624,7 +4500,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.1.6" + "source": "https://github.com/spatie/array-to-xml/tree/3.2.0" }, "funding": [ { @@ -4636,7 +4512,7 @@ "type": "github" } ], - "time": "2023-05-11T14:04:07+00:00" + "time": "2023-07-19T18:30:26+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -4697,23 +4573,23 @@ }, { "name": "symfony/console", - "version": "v6.2.11", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77" + "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5aa03db8ef0a5457c316ec580e69562d97734c77", - "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77", + "url": "https://api.github.com/repos/symfony/console/zipball/8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", + "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/string": "^5.4|^6.0" }, "conflict": { @@ -4735,12 +4611,6 @@ "symfony/process": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, "type": "library", "autoload": { "psr-4": { @@ -4773,7 +4643,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.2.11" + "source": "https://github.com/symfony/console/tree/v6.3.0" }, "funding": [ { @@ -4789,20 +4659,20 @@ "type": "tidelift" } ], - "time": "2023-05-26T08:16:21+00:00" + "time": "2023-05-29T12:49:39+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { @@ -4811,7 +4681,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -4840,7 +4710,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" }, "funding": [ { @@ -4856,20 +4726,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:25:55+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/filesystem", - "version": "v6.2.10", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894" + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd588debf7d1bc16a2c84b4b3b71145d9946b894", - "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", "shasum": "" }, "require": { @@ -4903,7 +4773,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.2.10" + "source": "https://github.com/symfony/filesystem/tree/v6.3.1" }, "funding": [ { @@ -4919,7 +4789,7 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:46:08+00:00" + "time": "2023-06-01T08:30:39+00:00" }, { "name": "symfony/polyfill-ctype", @@ -5336,16 +5206,16 @@ }, { "name": "symfony/string", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef" + "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/193e83bbd6617d6b2151c37fff10fa7168ebddef", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef", + "url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f", + "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f", "shasum": "" }, "require": { @@ -5356,13 +5226,13 @@ "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { "symfony/error-handler": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", "symfony/intl": "^6.2", - "symfony/translation-contracts": "^2.0|^3.0", + "symfony/translation-contracts": "^2.5|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", @@ -5402,7 +5272,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.2.8" + "source": "https://github.com/symfony/string/tree/v6.3.0" }, "funding": [ { @@ -5418,7 +5288,7 @@ "type": "tidelift" } ], - "time": "2023-03-20T16:06:02+00:00" + "time": "2023-03-21T21:06:29+00:00" }, { "name": "theseer/tokenizer", @@ -5472,16 +5342,16 @@ }, { "name": "vimeo/psalm", - "version": "5.12.0", + "version": "5.13.1", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176" + "reference": "086b94371304750d1c673315321a55d15fc59015" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/f90118cdeacd0088e7215e64c0c99ceca819e176", - "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/086b94371304750d1c673315321a55d15fc59015", + "reference": "086b94371304750d1c673315321a55d15fc59015", "shasum": "" }, "require": { @@ -5572,9 +5442,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.12.0" + "source": "https://github.com/vimeo/psalm/tree/5.13.1" }, - "time": "2023-05-22T21:19:03+00:00" + "time": "2023-06-27T16:39:49+00:00" }, { "name": "webimpress/coding-standard", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 69cb15d6d..63b4bd3dc 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -3,29 +3,29 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="./vendor/autoload.php" - convertDeprecationsToExceptions="true" - colors="true"> + colors="true" + cacheDirectory=".phpunit.cache" + displayDetailsOnSkippedTests="true" + displayDetailsOnTestsThatTriggerDeprecations="true" + displayDetailsOnTestsThatTriggerErrors="true" + displayDetailsOnTestsThatTriggerNotices="true" + displayDetailsOnTestsThatTriggerWarnings="true" + displayDetailsOnIncompleteTests="true" + failOnWarning="true" + failOnDeprecation="true" + failOnNotice="true" +> ./test/ - - - - disable - - - - - - ./src - - - - - + + + ./src + + diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 74aa7aded..751335303 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + $templatePath @@ -30,6 +30,8 @@ $closingBracket $closingBracket $closingBracket + $closingBracket + $closingBracket $val @@ -183,18 +185,9 @@ - + $item - - - getContainer()->set($value)]]> - - - HeadLink - - - (object) $attributes - + offsetSet @@ -207,10 +200,8 @@ $href $index $item - $item autoEscape ? $this->escapeAttribute($attributes[$itemKey]) : $attributes[$itemKey]]]> autoEscape ? $this->escapeAttribute($value) : $value]]> - getSeparator()]]> $value @@ -227,42 +218,16 @@ $extras $href $href - $indent $index $item - $item - $item $media $title $type $value - - HeadLink - - - $indent - $indent - - - href]]> - rel]]> - - - - - - $value - - - stdClass - $index - - $item - $index view]]> @@ -270,24 +235,13 @@ (string) $conditionalStylesheet - - getIndent - getSeparator - getWhitespace - setSeparator - - - ! $item instanceof stdClass - - + $item $value - - - $item - + $value + offsetSet offsetUnset @@ -297,7 +251,6 @@ $args[1] $args[2] $index - $item $type]]> content]]> type]]> @@ -305,22 +258,19 @@ autoEscape ? $this->escapeAttribute($item->$type) : $item->$type]]> autoEscape ? $this->escapeAttribute($item->content) : $item->content]]> autoEscape ? $this->escapeAttribute($value) : $value]]> - getSeparator()]]> $type $value + $value $doctype - $indent $index - $item - $item $key $type $value - HeadMeta + $this isHtml5 @@ -330,24 +280,10 @@ isRdfa isXhtml - - $indent - $indent - - - type]]> - {$item->type}]]> - parent::__call($method, $args) parent::__call($method, $args) - - $value - - - offsetSet($index, $item)]]> - $index $index @@ -365,67 +301,35 @@ plugin plugin - - getIndent - getSeparator - getWhitespace - setSeparator - - - - offsetSet $content $content - $indent $index $index - attributes]]> - attributes['conditional']]]> - type]]> - type]]> - $key autoEscape ? $this->escapeAttribute($value) : $value]]> - getSeparator()]]> $value + + $attrs + $attrs + $content - $indent $index - $item - $item - $key - captureType]]> - $type - $useCdata $value - HeadScript + $this isHtml5 - isXhtml - - attributes['conditional']]]> - source]]> - $type - - - attributes]]> - attributes]]> - source]]> - source]]> - type]]> - parent::__call($method, $args) parent::__call($method, $args) @@ -433,14 +337,6 @@ $index - - null - - - $captureLock - $captureScriptType - $captureType - (bool) $flag @@ -450,113 +346,38 @@ plugin - plugin - - getIndent - getSeparator - getWhitespace - setSeparator - + + content)]]> + content)]]> + content) || ! is_string($item->content)]]> + offsetSet + + ObjectShape + $content - $enc - escapeHtmlAttr($value)]]> - $indent $index - $item - attributes['conditional']]]> - $key - $value - + $attrs - - attributes['conditional']]]> - $content - $enc - $escaper - $indent $index - $item - $key - $value - - escapeHtmlAttr - - - $indent - $indent - attributes['conditional']]]> - content]]> - $index - - $escapeEnd - $escapeStart - - - $attrs - null - - - $captureAttrs - $captureLock - $captureType - is_string($content) - - getIndent - getSeparator - getWhitespace - setSeparator - - - - - $item - $item - - - $item]]> - - - $item - $separator - - - $items - - - $indent - $item - $items[] - $postfix - $prefix - $separator - - - $indent - $postfix - $prefix - - - translate - @@ -607,19 +428,6 @@ (bool) $useNamespaces - - - parent::__invoke($mode, $spec, $placement, $attrs, $type) - - - InlineScript - - - InlineScript - InlineScript - InlineScript - - plugin @@ -1188,124 +996,68 @@ - - containerClass($value)]]> - - - items[$key]]]> - - - AbstractContainer - - - items]]> - (string) $key (string) $key (string) $key (string) $key - - - - Container - Container - + + containerClass($value)]]> + - self + $this + + $data + $data + $data + $data + nextIndex()]]> + nextIndex()]]> + $this[$key] .= $data + + + max($keys) + 1 + + + int + __toString - - AbstractContainer - $items + getArrayCopy()]]> + $values - - $this[$key] - - - $key - - - int - $this[$key] max($keys) - - max($keys) + 1 - - - $captureKey - $captureType - - (string) $indent (string) $postfix (string) $prefix (string) $separator - - captureKey]]> - - - containerClass()]]> - - - container]]> - __toString - - ArrayAccess - IteratorAggregate - - $container[$key] $return - - string - string - - - escapeHtml - escapeHtmlAttr - - - getEscaper()->escapeHtml((string) $string)]]> - getEscaper()->escapeHtmlAttr((string) $string)]]> - - - AbstractContainer - - - $enc - - - null - - - containerClass()]]> - (bool) $autoEscape (string) $string (string) $string - - container]]> - + + containerClass()]]> + @@ -1534,9 +1286,6 @@ $captureTo - - getCode()]]> - @@ -1635,9 +1384,6 @@ $children $values - - getCode()]]> - (bool) $mergeUnnamedChildren (string) $callback @@ -1803,6 +1549,7 @@ $value $value $value + $value lastLookupFailure]]> @@ -1813,6 +1560,7 @@ paths]]> + (bool) $flag (bool) $flag (string) $defaultSuffix @@ -2034,10 +1782,6 @@ - - - - @@ -2053,7 +1797,6 @@ $item $item $item - $item $order[$key] @@ -2078,9 +1821,6 @@ $value $value - - iterable - @@ -2095,12 +1835,6 @@ - conditionalStylesheet]]> - conditionalStylesheet]]> - conditionalStylesheet]]> - conditionalStylesheet]]> - conditionalStylesheet]]> - media]]> href]]> href]]> href]]> @@ -2118,7 +1852,6 @@ getValue getValue getValue - setIndent @@ -2126,242 +1859,15 @@ - - - - - - - $item - $item - $item - $item - $item - $item - $item - $item - $item - $item - $item - $item - type]]> - type]]> - type]]> - $modifiers - $modifiers - $value - $values - $values - $values - $values - $values - $values - $values - $values - $values - - - - - $values[$i] - $values[100] - - - $item - $item - $item - $item - $item - $modifiers - $value - $values - $values - $values - $values - $values - - - - - - - content]]> - content]]> - content]]> - content]]> - content]]> - name]]> - name]]> - type]]> - type]]> - type]]> - type]]> - type]]> - {$item->type}]]> - {$item->type}]]> - {$item->type}]]> - modifiers]]> - - getArrayCopy - getArrayCopy - getArrayCopy - getArrayCopy - getArrayCopy - getValue offsetSetHttpEquiv offsetSetHttpEquiv offsetSetName offsetSetName offsetSetName - setIndent - - - - - public function booleanAttributeDataProvider(): Generator - - - - - - - - $item - $item - $item - source]]> - $values - $values - $values - $values - $values - $values - $values - - - attributes['src']]]> - $items[$i] - $values[$i] - $values[$i] - $values[$i] - attributes['src']]]> - $values[0] - $values[0] - $values[0] - attributes['src']]]> - $values[5] - $values[5] - $values[5] - attributes['src']]]> - - - $first - $item - $item - $items - $values - $values - $values - $values - $values - - - ]]> - - - attributes]]> - source]]> - type]]> - attributes]]> - source]]> - source]]> - source]]> - attributes]]> - source]]> - type]]> - attributes]]> - source]]> - type]]> - attributes]]> - source]]> - type]]> - - - getArrayCopy - getArrayCopy - getArrayCopy - getArrayCopy - getArrayCopy - getArrayCopy - setIndent - setIndent - - - - - content]]> - content]]> - $value - $values - $values - $values - $values - $values - $values - $values - $values - content]]> - content]]> - content]]> - - - $values[$i] - $values[0] - $values[1] - $values[2] - - - $item - $item - $value - $values - $values - $values - $values - $values - - - content]]> - content]]> - attributes]]> - content]]> - content]]> - content]]> - - - bogusMethod - getArrayCopy - getArrayCopy - getArrayCopy - getArrayCopy - getArrayCopy - getArrayCopy - getValue - setIndent - setIndent - setIndent - - - $placeholder - - - renderTitle - - $escape($value) @@ -2388,27 +1894,10 @@ _helper]]> - + getDependencyConfig())]]> - - $app - - - bootstrap - getMvcEvent - loadModules - setRouteMatch - - - null - null - null - - - - @@ -2688,8 +2177,6 @@ $o $o $o - $o - $o $rIterator $rIterator $rIterator @@ -2707,7 +2194,6 @@ $key $key $key - $key $value $value $value @@ -2721,12 +2207,6 @@ $value $value - - $item - $item - $item - $item - $result $result @@ -2791,10 +2271,6 @@ addPath addPath - - new TestAsset\BogusIteratorTest($data) - new TestAsset\BogusIteratorTest($data) - addPath addPath @@ -2830,9 +2306,6 @@ message]]> - $data - $data - $key $key $key $key @@ -2917,40 +2390,10 @@ translations]]> - - - Bar - Bar - - - - - Iterator - - - - - Iterator - - $value - - AllowDynamicProperties - - - - - MockContainer - MockContainer - - - - - Iterator - @@ -3004,14 +2447,6 @@ 'factories' => $factories, ])]]> - - $target - - - $alias - $aliases - $target - ]]> diff --git a/src/Helper/HeadLink.php b/src/Helper/HeadLink.php index 96c0f6a64..8f34f209a 100644 --- a/src/Helper/HeadLink.php +++ b/src/Helper/HeadLink.php @@ -5,17 +5,18 @@ namespace Laminas\View\Helper; use Laminas\View\Exception; +use Laminas\View\Helper\Placeholder\Container\AbstractContainer; +use Laminas\View\Helper\Placeholder\Container\AbstractStandalone; use stdClass; use function array_intersect; use function array_keys; use function array_shift; -use function call_user_func_array; use function count; -use function func_get_args; use function get_object_vars; use function implode; use function is_array; +use function is_object; use function is_string; use function method_exists; use function preg_match; @@ -24,11 +25,8 @@ use const PHP_EOL; -// @codingStandardsIgnoreStart /** - * Laminas_Layout_View_Helper_HeadLink - * - * @see http://www.w3.org/TR/xhtml1/dtds.html + * @extends AbstractStandalone * * Creates the following virtual methods: * @method HeadLink appendStylesheet($href, $media = 'screen', $conditionalStylesheet = '', $extras = []) @@ -39,9 +37,9 @@ * @method HeadLink offsetSetAlternate($index, $href, $type, $title, $extras = []) * @method HeadLink prependAlternate($href, $type, $title, $extras = []) * @method HeadLink setAlternate($href, $type, $title, $extras = []) + * @final */ -class HeadLink extends Placeholder\Container\AbstractStandalone -// @codingStandardsIgnoreEnd +class HeadLink extends AbstractStandalone { /** * Allowed attributes @@ -84,13 +82,13 @@ public function __construct() * Allows calling $helper->headLink(), but, more importantly, chaining calls * like ->appendStylesheet()->headLink(). * - * @param array|null $attributes + * @param array|null $attributes * @param string $placement * @return HeadLink */ - public function headLink(?array $attributes = null, $placement = Placeholder\Container\AbstractContainer::APPEND) + public function headLink(?array $attributes = null, $placement = AbstractContainer::APPEND) { - return call_user_func_array([$this, '__invoke'], func_get_args()); + return $this->__invoke($attributes, $placement); } /** @@ -99,22 +97,22 @@ public function headLink(?array $attributes = null, $placement = Placeholder\Con * Returns current object instance. Optionally, allows passing array of * values to build link. * - * @param array|null $attributes - * @param string $placement - * @return HeadLink + * @param array|null $attributes + * @param string $placement + * @return $this */ - public function __invoke(?array $attributes = null, $placement = Placeholder\Container\AbstractContainer::APPEND) + public function __invoke(?array $attributes = null, $placement = AbstractContainer::APPEND) { if (null !== $attributes) { $item = $this->createData($attributes); switch ($placement) { - case Placeholder\Container\AbstractContainer::SET: + case AbstractContainer::SET: $this->set($item); break; - case Placeholder\Container\AbstractContainer::PREPEND: + case AbstractContainer::PREPEND: $this->prepend($item); break; - case Placeholder\Container\AbstractContainer::APPEND: + case AbstractContainer::APPEND: default: $this->append($item); break; @@ -201,12 +199,14 @@ public function __call($method, $args) /** * Check if value is valid * - * @param mixed $value + * @internal This method will become private in version 3.0 + * + * @param mixed $value * @return bool */ protected function isValid($value) { - if (! $value instanceof stdClass) { + if (! is_object($value)) { return false; } @@ -223,9 +223,9 @@ protected function isValid($value) /** * append() * - * @param mixed $value + * @param object $value * @throws Exception\InvalidArgumentException - * @return Placeholder\Container\AbstractContainer + * @return AbstractContainer */ public function append($value) { @@ -241,8 +241,8 @@ public function append($value) /** * offsetSet() * - * @param string|int $index - * @param array $value + * @param int $index + * @param object $value * @throws Exception\InvalidArgumentException * @return void */ @@ -260,9 +260,9 @@ public function offsetSet($index, $value) /** * prepend() * - * @param mixed $value + * @param object $value * @throws Exception\InvalidArgumentException - * @return Placeholder\Container\AbstractContainer + * @return AbstractContainer */ public function prepend($value) { @@ -278,9 +278,9 @@ public function prepend($value) /** * set() * - * @param array $value + * @param object $value * @throws Exception\InvalidArgumentException - * @return HeadLink + * @return $this */ public function set($value) { @@ -290,12 +290,16 @@ public function set($value) ); } - return $this->getContainer()->set($value); + $this->getContainer()->set($value); + + return $this; } /** * Create HTML link element from data item * + * @internal This method will become private in version 3.0 + * * @return string */ public function itemToString(stdClass $item) @@ -356,24 +360,27 @@ public function itemToString(stdClass $item) */ public function toString($indent = null) { - $indent = null !== $indent - ? $this->getWhitespace($indent) - : $this->getIndent(); + $container = $this->getContainer(); + $indent = null !== $indent + ? $container->getWhitespace($indent) + : $container->getIndent(); $items = []; - $this->getContainer()->ksort(); - foreach ($this as $item) { + $container->ksort(); + foreach ($container as $item) { $items[] = $this->itemToString($item); } - return $indent . implode($this->escape($this->getSeparator()) . $indent, $items); + return $indent . implode($this->escape($container->getSeparator()) . $indent, $items); } /** * Create data item for stack * - * @param array $attributes - * @return stdClass + * @internal This method will become private in version 3.0 + * + * @param array $attributes + * @return object */ public function createData(array $attributes) { @@ -383,8 +390,10 @@ public function createData(array $attributes) /** * Create item for stylesheet link item * + * @deprecated This method is unused and will be removed in version 3.0 of this component + * * @param array $args - * @return stdClass|false Returns false if stylesheet is a duplicate + * @return object|false Returns false if stylesheet is a duplicate */ public function createDataStylesheet(array $args) { @@ -435,6 +444,8 @@ public function createDataStylesheet(array $args) /** * Is the linked stylesheet a duplicate? * + * @internal This method will become private in version 3.0 + * * @param string $uri * @return bool */ @@ -452,9 +463,11 @@ protected function isDuplicateStylesheet($uri) /** * Create item for alternate link item * + * @deprecated This method is unused and will be removed in version 3.0 of this component + * * @param array $args * @throws Exception\InvalidArgumentException - * @return stdClass + * @return object */ public function createDataAlternate(array $args) { @@ -493,8 +506,10 @@ public function createDataAlternate(array $args) /** * Create item for a prev relationship (mainly used for pagination) * + * @deprecated This method is unused and will be removed in version 3.0 of this component + * * @param array $args - * @return stdClass + * @return object */ public function createDataPrev(array $args) { @@ -507,8 +522,10 @@ public function createDataPrev(array $args) /** * Create item for a prev relationship (mainly used for pagination) * + * @deprecated This method is unused and will be removed in version 3.0 of this component + * * @param array $args - * @return stdClass + * @return object */ public function createDataNext(array $args) { diff --git a/src/Helper/HeadMeta.php b/src/Helper/HeadMeta.php index 8e460b295..d6ca47188 100644 --- a/src/Helper/HeadMeta.php +++ b/src/Helper/HeadMeta.php @@ -6,6 +6,8 @@ use Laminas\View; use Laminas\View\Exception; +use Laminas\View\Helper\Placeholder\Container\AbstractContainer; +use Laminas\View\Helper\Placeholder\Container\AbstractStandalone; use stdClass; use function array_shift; @@ -14,6 +16,7 @@ use function count; use function implode; use function in_array; +use function is_object; use function is_string; use function method_exists; use function preg_match; @@ -49,40 +52,50 @@ * @method HeadMeta offsetGetItemprop($index, $keyValue, $content, $modifiers = array()) * @method HeadMeta prependItemprop($keyValue, $content, $modifiers = array()) * @method HeadMeta setItemprop($keyValue, $content, $modifiers = array()) + * + * @psalm-type ObjectShape = object{ + * type: string, + * content: string, + * modifiers: array, + * name?: string, + * http-equiv?: string, + * charset?: string, + * property?: string, + * itemprop?: string, + * } + * @extends AbstractStandalone + * @final */ -class HeadMeta extends Placeholder\Container\AbstractStandalone +class HeadMeta extends AbstractStandalone { /** * Allowed key types * - * @var array + * @var list */ protected $typeKeys = ['name', 'http-equiv', 'charset', 'property', 'itemprop']; /** * Required attributes for meta tag * - * @var array + * @deprecated This property is unused and will be removed in version 3.0 + * + * @var list */ protected $requiredKeys = ['content']; /** * Allowed modifier keys * - * @var array + * @var list */ protected $modifierKeys = ['lang', 'scheme']; - /** - * Constructor - * - * Set separator to PHP_EOL - */ public function __construct() { parent::__construct(); - $this->setSeparator(PHP_EOL); + $this->getContainer()->setSeparator(PHP_EOL); } /** @@ -93,14 +106,14 @@ public function __construct() * @param string $keyType * @param array $modifiers * @param string $placement - * @return HeadMeta + * @return $this */ public function __invoke( $content = null, $keyValue = null, $keyType = 'name', $modifiers = [], - $placement = Placeholder\Container\AbstractContainer::APPEND + $placement = AbstractContainer::APPEND ) { if ((null !== $content) && (null !== $keyValue)) { $item = $this->createData($keyType, $keyValue, $content, $modifiers); @@ -126,7 +139,7 @@ public function __invoke( * @param string $method * @param array $args * @throws Exception\BadMethodCallException - * @return HeadMeta + * @return $this */ public function __call($method, $args) { @@ -162,7 +175,9 @@ public function __call($method, $args) $item = $this->createData($type, $args[0], $args[1], $args[2]); if ('offsetSet' === $action) { - return $this->offsetSet($index, $item); + $this->offsetSet($index, $item); + + return $this; } $this->$action($item); @@ -181,19 +196,20 @@ public function __call($method, $args) */ public function toString($indent = null) { - $indent = null !== $indent - ? $this->getWhitespace($indent) - : $this->getIndent(); + $container = $this->getContainer(); + $indent = null !== $indent + ? $container->getWhitespace($indent) + : $container->getIndent(); $items = []; - $this->getContainer()->ksort(); + $container->ksort(); $doctype = $this->view->plugin('doctype'); assert($doctype instanceof Doctype); $isHtml5 = $doctype->isHtml5(); try { - foreach ($this as $item) { + foreach ($container as $item) { $content = $this->itemToString($item); if ($isHtml5 && $item->type === 'charset') { @@ -208,32 +224,35 @@ public function toString($indent = null) return ''; } - return $indent . implode($this->escape($this->getSeparator()) . $indent, $items); + return $indent . implode($this->escape($container->getSeparator()) . $indent, $items); } /** * Create data item for inserting into stack * + * @internal This method will become private in version 3.0 + * * @param string $type * @param string $typeValue * @param string $content * @param array $modifiers - * @return stdClass + * @return object */ public function createData($type, $typeValue, $content, array $modifiers) { - $data = new stdClass(); - $data->type = $type; - $data->$type = $typeValue; - $data->content = $content; - $data->modifiers = $modifiers; - - return $data; + return (object) [ + 'type' => $type, + $type => $typeValue, + 'content' => $content, + 'modifiers' => $modifiers, + ]; } /** * Build meta HTML string * + * @internal This method will become private in version 3.0 + * * @throws Exception\InvalidArgumentException * @return string */ @@ -312,6 +331,8 @@ public function itemToString(stdClass $item) /** * Normalize type attribute of meta * + * @internal This method will become private in version 3.0 + * * @param string $type type in CamelCase * @throws Exception\DomainException * @return string @@ -338,13 +359,15 @@ protected function normalizeType($type) /** * Determine if item is valid * - * @param stdClass $item + * @internal This method will become private in version 3.0 + * + * @param mixed $item * @return bool */ protected function isValid($item) { if ( - ! $item instanceof stdClass + ! is_object($item) || ! isset($item->type) || ! isset($item->modifiers) ) { @@ -386,7 +409,7 @@ protected function isValid($item) /** * Append * - * @param stdClass $value + * @param object $value * @return View\Helper\Placeholder\Container\AbstractContainer * @throws Exception\InvalidArgumentException */ @@ -404,8 +427,8 @@ public function append($value) /** * OffsetSet * - * @param string|int $index - * @param string $value + * @param int $index + * @param mixed $value * @return void * @throws Exception\InvalidArgumentException */ @@ -423,7 +446,7 @@ public function offsetSet($index, $value) /** * OffsetUnset * - * @param string|int $index + * @param int $index * @return void * @throws Exception\InvalidArgumentException */ @@ -439,9 +462,9 @@ public function offsetUnset($index) /** * Prepend * - * @param stdClass $value + * @param object $value * @throws Exception\InvalidArgumentException - * @return View\Helper\Placeholder\Container\AbstractContainer + * @return AbstractContainer */ public function prepend($value) { @@ -457,9 +480,9 @@ public function prepend($value) /** * Set * - * @param stdClass $value + * @param object $value * @throws Exception\InvalidArgumentException - * @return View\Helper\Placeholder\Container\AbstractContainer + * @return AbstractContainer */ public function set($value) { @@ -484,15 +507,16 @@ public function set($value) * * @param string $charset * @throws Exception\InvalidArgumentException - * @return static + * @return $this */ public function setCharset($charset) { - $item = new stdClass(); - $item->type = 'charset'; - $item->charset = $charset; - $item->content = null; - $item->modifiers = []; + $item = (object) [ + 'type' => 'charset', + 'charset' => $charset, + 'content' => null, + 'modifiers' => [], + ]; if (! $this->isValid($item)) { throw new Exception\InvalidArgumentException( diff --git a/src/Helper/HeadScript.php b/src/Helper/HeadScript.php index 880cf594b..78f5c5e19 100644 --- a/src/Helper/HeadScript.php +++ b/src/Helper/HeadScript.php @@ -5,14 +5,18 @@ namespace Laminas\View\Helper; use Laminas\View\Exception; -use stdClass; +use Laminas\View\Helper\Placeholder\Container\AbstractContainer; +use Laminas\View\Helper\Placeholder\Container\AbstractStandalone; +use Laminas\View\Renderer\PhpRenderer; use function array_key_exists; use function array_shift; +use function assert; use function count; use function filter_var; use function implode; use function in_array; +use function is_object; use function is_string; use function ob_get_clean; use function ob_start; @@ -38,8 +42,14 @@ * @method HeadScript offsetSetScript($index, $src, $type = 'text/javascript', $attrs = []) * @method HeadScript prependScript($script, $type = 'text/javascript', $attrs = []) * @method HeadScript setScript($script, $type = 'text/javascript', $attrs = []) + * @psalm-type ObjectShape = object{ + * type: string, + * attributes: array, + * source: string|null, + * } + * @extends AbstractStandalone */ -class HeadScript extends Placeholder\Container\AbstractStandalone +class HeadScript extends AbstractStandalone { /** * Script type constants @@ -66,33 +76,33 @@ class HeadScript extends Placeholder\Container\AbstractStandalone * * @var bool */ - protected $captureLock; + protected $captureLock = false; /** * Capture type * - * @var string + * @var string|null */ protected $captureScriptType; /** * Capture attributes * - * @var null|array + * @var null|array */ protected $captureScriptAttrs; /** * Capture type (append, prepend, set) * - * @var string + * @var string|null */ protected $captureType; /** * Optional allowed attributes for script tag * - * @var array + * @var list */ protected $optionalAttributes = [ 'charset', @@ -111,7 +121,7 @@ class HeadScript extends Placeholder\Container\AbstractStandalone /** * Script attributes that behave as booleans * - * @var string[] + * @var list */ private array $booleanAttributes = [ 'nomodule', @@ -122,7 +132,9 @@ class HeadScript extends Placeholder\Container\AbstractStandalone /** * Required attributes for script tag * - * @var string + * @deprecated This property is unused and will be removed in version 3.0 of this component + * + * @var list */ protected $requiredAttributes = ['type']; @@ -134,16 +146,11 @@ class HeadScript extends Placeholder\Container\AbstractStandalone */ public $useCdata = false; - /** - * Constructor - * - * Set separator to PHP_EOL. - */ public function __construct() { parent::__construct(); - $this->setSeparator(PHP_EOL); + $this->getContainer()->setSeparator(PHP_EOL); } /** @@ -155,9 +162,9 @@ public function __construct() * @param string $mode Script or file * @param string $spec Script/url * @param string $placement Append, prepend, or set - * @param array $attrs Array of script attributes + * @param array $attrs Array of script attributes * @param string $type Script type and/or array of script attributes - * @return HeadScript + * @return $this */ public function __invoke( $mode = self::FILE, @@ -191,7 +198,7 @@ public function __invoke( * @param string $method Method to call * @param array $args Arguments of method * @throws Exception\BadMethodCallException If too few arguments or invalid method. - * @return HeadScript + * @return $this */ public function __call($method, $args) { @@ -265,12 +272,16 @@ public function __call($method, $args) */ public function toString($indent = null) { - $indent = null !== $indent - ? $this->getWhitespace($indent) - : $this->getIndent(); + $container = $this->getContainer(); + $indent = null !== $indent + ? $container->getWhitespace($indent) + : $container->getIndent(); + + if ($this->view instanceof PhpRenderer) { + $doctype = $this->view->plugin('doctype'); + assert($doctype instanceof Doctype); - if ($this->view) { - $useCdata = $this->view->plugin('doctype')->isXhtml(); + $useCdata = $doctype->isXhtml(); } else { $useCdata = $this->useCdata; } @@ -279,8 +290,8 @@ public function toString($indent = null) $escapeEnd = $useCdata ? '//]]>' : '//-->'; $items = []; - $this->getContainer()->ksort(); - foreach ($this as $item) { + $container->ksort(); + foreach ($container as $item) { if (! $this->isValid($item)) { continue; } @@ -288,20 +299,20 @@ public function toString($indent = null) $items[] = $this->itemToString($item, $indent, $escapeStart, $escapeEnd); } - return implode($this->getSeparator(), $items); + return implode($container->getSeparator(), $items); } /** * Start capture action * - * @param mixed $captureType Type of capture - * @param string $type Type of script - * @param array $attrs Attributes of capture + * @param string $captureType Type of capture + * @param string $type Type of script + * @param array $attrs Attributes of capture * @throws Exception\RuntimeException * @return void */ public function captureStart( - $captureType = Placeholder\Container\AbstractContainer::APPEND, + $captureType = AbstractContainer::APPEND, $type = self::DEFAULT_SCRIPT_TYPE, $attrs = [] ) { @@ -331,9 +342,9 @@ public function captureEnd() $this->captureLock = false; switch ($this->captureType) { - case Placeholder\Container\AbstractContainer::SET: - case Placeholder\Container\AbstractContainer::PREPEND: - case Placeholder\Container\AbstractContainer::APPEND: + case AbstractContainer::SET: + case AbstractContainer::PREPEND: + case AbstractContainer::APPEND: $action = strtolower($this->captureType) . 'Script'; break; default: @@ -347,19 +358,20 @@ public function captureEnd() /** * Create data item containing all necessary components of script * + * @internal This method will become private in version 3.0 + * * @param string $type Type of data - * @param array $attributes Attributes of data + * @param array $attributes Attributes of data * @param string $content Content of data - * @return stdClass + * @return ObjectShape */ public function createData($type, array $attributes, $content = null) { - $data = new stdClass(); - $data->type = $type; - $data->attributes = $attributes; - $data->source = $content; - - return $data; + return (object) [ + 'type' => $type, + 'attributes' => $attributes, + 'source' => $content, + ]; } /** @@ -386,13 +398,15 @@ protected function isDuplicate($file) /** * Is the script provided valid? * - * @param mixed $value Is the given script valid? + * @internal This method will become private in version 3.0 + * + * @param mixed $value Is the given script valid? * @return bool */ protected function isValid($value) { if ( - ! $value instanceof stdClass + ! is_object($value) || ! isset($value->type) || (! isset($value->source) && ! isset($value->attributes)) @@ -406,10 +420,12 @@ protected function isValid($value) /** * Create script HTML * - * @param mixed $item Item to convert - * @param string $indent String to add before the item - * @param string $escapeStart Starting sequence - * @param string $escapeEnd Ending sequence + * @internal This method will become private in version 3.0 + * + * @param ObjectShape $item Item to convert + * @param string $indent String to add before the item + * @param string $escapeStart Starting sequence + * @param string $escapeEnd Ending sequence * @return string */ public function itemToString($item, $indent, $escapeStart, $escapeEnd) @@ -484,9 +500,9 @@ public function itemToString($item, $indent, $escapeStart, $escapeEnd) /** * Override append * - * @param string $value Append script or file + * @param ObjectShape $value Append script or file * @throws Exception\InvalidArgumentException - * @return Placeholder\Container\AbstractContainer + * @return AbstractContainer */ public function append($value) { @@ -503,9 +519,9 @@ public function append($value) /** * Override prepend * - * @param string $value Prepend script or file + * @param ObjectShape $value Prepend script or file * @throws Exception\InvalidArgumentException - * @return Placeholder\Container\AbstractContainer + * @return AbstractContainer */ public function prepend($value) { @@ -522,7 +538,7 @@ public function prepend($value) /** * Override set * - * @param string $value Set script or file + * @param ObjectShape $value Set script or file * @throws Exception\InvalidArgumentException * @return void */ @@ -540,8 +556,8 @@ public function set($value) /** * Override offsetSet * - * @param string|int $index Set script of file offset - * @param mixed $value + * @param int $index Set script of file offset + * @param ObjectShape $value * @throws Exception\InvalidArgumentException * @return void */ @@ -561,7 +577,7 @@ public function offsetSet($index, $value) * Set flag indicating if arbitrary attributes are allowed * * @param bool $flag Set flag - * @return HeadScript + * @return $this */ public function setAllowArbitraryAttributes($flag) { diff --git a/src/Helper/HeadStyle.php b/src/Helper/HeadStyle.php index 701e70fa7..f8ebe24e5 100644 --- a/src/Helper/HeadStyle.php +++ b/src/Helper/HeadStyle.php @@ -6,11 +6,13 @@ use Laminas\View; use Laminas\View\Exception; +use Laminas\View\Helper\Placeholder\Container\AbstractContainer; +use Laminas\View\Helper\Placeholder\Container\AbstractStandalone; use stdClass; +use function array_filter; use function array_shift; use function count; -use function explode; use function implode; use function in_array; use function is_array; @@ -22,36 +24,45 @@ use function preg_replace; use function sprintf; use function str_replace; -use function strpos; use function strtoupper; -use function substr; -use function trim; +use const ARRAY_FILTER_USE_KEY; use const PHP_EOL; /** - * Helper for setting and retrieving stylesheets + * Helper for adding inline CSS to the head in style tags * - * Allows the following method calls: + * @psalm-type ObjectShape = object{ + * attributes: array, + * content: string, + * } + * @extends AbstractStandalone * - * @method HeadStyle appendStyle($content, $attributes = array()) - * @method HeadStyle offsetSetStyle($index, $content, $attributes = array()) - * @method HeadStyle prependStyle($content, $attributes = array()) - * @method HeadStyle setStyle($content, $attributes = array()) + * Allows the following method calls: + * @method HeadStyle appendStyle(string $content, array $attributes = []) + * @method HeadStyle offsetSetStyle(int $index, string $content, array $attributes = []) + * @method HeadStyle prependStyle(string $content, array $attributes = []) + * @method HeadStyle setStyle(string $content, array $attributes = []) + * @method HeadStyle setIndent(int|string $indent) + * @final */ -class HeadStyle extends Placeholder\Container\AbstractStandalone +class HeadStyle extends AbstractStandalone { /** * Allowed optional attributes * - * @var array + * @var list */ - protected $optionalAttributes = ['lang', 'title', 'media', 'dir']; + protected $optionalAttributes = ['lang', 'title', 'media', 'dir', 'nonce']; /** * Allowed media types * - * @var array + * @deprecated This property is no longer used and will be removed in version 3.0 + * Because the media attribute can contain any type of media query, artificially limiting its values + * is counter-productive. + * + * @var list */ protected $mediaTypes = [ 'all', @@ -68,7 +79,7 @@ class HeadStyle extends Placeholder\Container\AbstractStandalone /** * Capture type and/or attributes (used for hinting during capture) * - * @var string + * @var array|null */ protected $captureAttrs; @@ -77,25 +88,20 @@ class HeadStyle extends Placeholder\Container\AbstractStandalone * * @var bool */ - protected $captureLock; + protected $captureLock = false; /** * Capture type (append, prepend, set) * - * @var string + * @var string|null */ protected $captureType; - /** - * Constructor - * - * Set separator to PHP_EOL. - */ public function __construct() { parent::__construct(); - $this->setSeparator(PHP_EOL); + $this->getContainer()->setSeparator(PHP_EOL); } /** @@ -108,17 +114,17 @@ public function __construct() * @param string|array $attributes Optional attributes to utilize * @return HeadStyle */ - public function __invoke($content = null, $placement = 'APPEND', $attributes = []) + public function __invoke($content = null, $placement = AbstractContainer::APPEND, $attributes = []) { if ((null !== $content) && is_string($content)) { switch (strtoupper($placement)) { - case 'SET': + case AbstractContainer::SET: $action = 'setStyle'; break; - case 'PREPEND': + case AbstractContainer::PREPEND: $action = 'prependStyle'; break; - case 'APPEND': + case AbstractContainer::APPEND: default: $action = 'appendStyle'; break; @@ -154,7 +160,7 @@ public function __call($method, $args) if (1 > $argc) { throw new Exception\BadMethodCallException(sprintf( 'Method "%s" requires minimally content for the stylesheet', - $method + $method, )); } @@ -186,34 +192,34 @@ public function __call($method, $args) */ public function toString($indent = null) { - $indent = null !== $indent - ? $this->getWhitespace($indent) - : $this->getIndent(); + $container = $this->getContainer(); + $indent = null !== $indent + ? $container->getWhitespace($indent) + : $container->getIndent(); $items = []; - $this->getContainer()->ksort(); - foreach ($this as $item) { + $container->ksort(); + foreach ($container as $item) { if (! $this->isValid($item)) { continue; } $items[] = $this->itemToString($item, $indent); } - $return = $indent . implode($this->getSeparator() . $indent, $items); - $return = preg_replace("/(\r\n?|\n)/", '$1' . $indent, $return); + $return = implode($container->getSeparator(), $items); - return $return; + return $indent . preg_replace("/(\r\n?|\n)/", '$1' . $indent, $return); } /** * Start capture action * * @param string $type - * @param string $attrs + * @param array|null $attrs optional style tag attributes * @throws Exception\RuntimeException * @return void */ - public function captureStart($type = Placeholder\Container\AbstractContainer::APPEND, $attrs = null) + public function captureStart($type = AbstractContainer::APPEND, $attrs = null) { if ($this->captureLock) { throw new Exception\RuntimeException('Cannot nest headStyle captures'); @@ -233,18 +239,18 @@ public function captureStart($type = Placeholder\Container\AbstractContainer::AP public function captureEnd() { $content = ob_get_clean(); - $attrs = $this->captureAttrs; + $attrs = $this->captureAttrs ?? []; $this->captureAttrs = null; $this->captureLock = false; switch ($this->captureType) { - case Placeholder\Container\AbstractContainer::SET: + case AbstractContainer::SET: $this->setStyle($content, $attrs); break; - case Placeholder\Container\AbstractContainer::PREPEND: + case AbstractContainer::PREPEND: $this->prependStyle($content, $attrs); break; - case Placeholder\Container\AbstractContainer::APPEND: + case AbstractContainer::APPEND: default: $this->appendStyle($content, $attrs); break; @@ -254,32 +260,32 @@ public function captureEnd() /** * Create data item for use in stack * + * @internal This method is internal and will be made private in version 3.0 + * * @param string $content - * @param array $attributes - * @return stdClass + * @param array $attributes + * @return ObjectShape */ public function createData($content, array $attributes) { if (! isset($attributes['media'])) { $attributes['media'] = 'screen'; - } elseif (is_array($attributes['media'])) { - $attributes['media'] = implode(',', $attributes['media']); } - $data = new stdClass(); - $data->content = $content; - $data->attributes = $attributes; - - return $data; + return (object) [ + 'content' => $content, + 'attributes' => $attributes, + ]; } /** * Determine if a value is a valid style tag * - * @param mixed $value + * @internal This method is internal and will be made private in version 3.0 + * * @return bool */ - protected function isValid($value) + protected function isValid(mixed $value) { if (! $value instanceof stdClass || ! isset($value->content) || ! isset($value->attributes)) { return false; @@ -288,67 +294,101 @@ protected function isValid($value) return true; } + private function viewEncoding(): string + { + $encoding = null; + if ($this->view !== null && method_exists($this->view, 'getEncoding')) { + /** @var mixed $encoding */ + $encoding = $this->view->getEncoding(); + } + + return is_string($encoding) ? $encoding : 'UTF-8'; + } + + /** + * @param array $value + * @psalm-assert array $value + */ + private static function assertAllString(array $value, string $message): void + { + /** @var mixed $item */ + foreach ($value as $item) { + if (is_string($item)) { + continue; + } + + throw new Exception\InvalidArgumentException($message); + } + } + + /** + * @param array $attributes + * @psalm-return array{media: non-empty-string, ...}|array + */ + private function normalizeMediaAttribute(array $attributes): array + { + if (! isset($attributes['media']) || $attributes['media'] === '' || $attributes['media'] === []) { + unset($attributes['media']); + + return $attributes; + } + + if (is_array($attributes['media'])) { + self::assertAllString( + $attributes['media'], + 'When the media attribute is an array, the array can only contain string values', + ); + + $attributes['media'] = implode(', ', $attributes['media']); + + return $attributes; + } + + return $attributes; + } + + private function styleTagAttributesString(object $item): string + { + $escaper = $this->getEscaper($this->viewEncoding()); + $attributes = isset($item->attributes) && is_array($item->attributes) ? $item->attributes : []; + $attributes = $this->normalizeMediaAttribute($attributes); + $attributes = array_filter( + $attributes, + fn (int|string $key) => in_array($key, $this->optionalAttributes, true), + ARRAY_FILTER_USE_KEY, + ); + + return (new View\HtmlAttributesSet($escaper, $attributes))->__toString(); + } + /** * Convert content and attributes into valid style tag * - * @param stdClass $item Item to render - * @param string $indent Indentation to use + * @internal This method is internal and will be made private in version 3.0 + * + * @param ObjectShape $item Item to render + * @param string $indent Indentation to use * @return string */ public function itemToString(stdClass $item, $indent) { - $attrString = ''; - if (! empty($item->attributes)) { - $enc = 'UTF-8'; - if ( - $this->view instanceof View\Renderer\RendererInterface - && method_exists($this->view, 'getEncoding') - ) { - $enc = $this->view->getEncoding(); - } - $escaper = $this->getEscaper($enc); - foreach ($item->attributes as $key => $value) { - if (! in_array($key, $this->optionalAttributes)) { - continue; - } - if ('media' === $key) { - if (false === strpos($value, ',')) { - if (! in_array($value, $this->mediaTypes)) { - continue; - } - } else { - $mediaTypes = explode(',', $value); - $value = ''; - foreach ($mediaTypes as $type) { - $type = trim($type); - if (! in_array($type, $this->mediaTypes)) { - continue; - } - $value .= $type . ','; - } - $value = substr($value, 0, -1); - } - } - $attrString .= sprintf(' %s="%s"', $key, $escaper->escapeHtmlAttr($value)); - } + if (! isset($item->content) || ! is_string($item->content) || $item->content === '') { + return ''; } - $escapeStart = $indent . '' . PHP_EOL; + $attrString = $this->styleTagAttributesString($item); + + $html = ''; + if ( isset($item->attributes['conditional']) && ! empty($item->attributes['conditional']) && is_string($item->attributes['conditional']) ) { - $escapeStart = null; - $escapeEnd = null; - } - - $html = ''; - - if (null === $escapeStart && null === $escapeEnd) { // inner wrap with comment end and start if !IE if (str_replace(' ', '', $item->attributes['conditional']) === '!IE') { $html = '' . $html . '', $string); } - public function argumentCountProvider(): iterable + /** @return array */ + public static function argumentCountProvider(): array { return [ 'One' => [1], @@ -305,7 +309,7 @@ public function argumentCountProvider(): iterable ]; } - /** @dataProvider argumentCountProvider */ + #[DataProvider('argumentCountProvider')] public function testSettingAlternateWithTooFewArgsRaisesException(int $argumentCount): void { $arguments = array_fill(0, $argumentCount, 'foo'); diff --git a/test/Helper/HeadMetaTest.php b/test/Helper/HeadMetaTest.php index f245e1e87..b47cb7527 100644 --- a/test/Helper/HeadMetaTest.php +++ b/test/Helper/HeadMetaTest.php @@ -4,30 +4,30 @@ namespace LaminasTest\View\Helper; +use Laminas\Escaper\Escaper; use Laminas\View\Exception; use Laminas\View\Exception\ExceptionInterface as ViewException; use Laminas\View\Helper; use Laminas\View\Helper\Doctype; -use Laminas\View\Helper\EscapeHtmlAttr; use Laminas\View\Helper\HeadMeta; use Laminas\View\Renderer\PhpRenderer as View; use PHPUnit\Framework\TestCase; use function array_shift; -use function count; +use function restore_error_handler; use function set_error_handler; use function sprintf; use function str_replace; use function substr_count; use function ucwords; +use const E_USER_WARNING; use const PHP_EOL; class HeadMetaTest extends TestCase { private HeadMeta $helper; - private EscapeHtmlAttr $attributeEscaper; - private ?string $error = null; + private Escaper $escaper; private View $view; /** @@ -42,12 +42,7 @@ protected function setUp(): void $doctype->__invoke('XHTML1_STRICT'); $this->helper = new HeadMeta(); $this->helper->setView($this->view); - $this->attributeEscaper = new EscapeHtmlAttr(); - } - - public function handleErrors(int $errno, string $errstr): void - { - $this->error = $errstr; + $this->escaper = new Escaper(); } public function testHeadMetaReturnsObjectInstance(): void @@ -99,14 +94,14 @@ protected function executeOverloadAppend(string $type): void for ($i = 0; $i < 3; ++$i) { $string .= ' foo'; $this->helper->$action('keywords', $string); - $values = $this->helper->getArrayCopy(); - $this->assertEquals($i + 1, count($values)); + $values = $this->helper->getContainer()->getArrayCopy(); + $this->assertCount($i + 1, $values); $item = $values[$i]; - $this->assertObjectHasAttribute('type', $item); - $this->assertObjectHasAttribute('modifiers', $item); - $this->assertObjectHasAttribute('content', $item); - $this->assertObjectHasAttribute($item->type, $item); + $this->assertObjectHasProperty('type', $item); + $this->assertObjectHasProperty('modifiers', $item); + $this->assertObjectHasProperty('content', $item); + $this->assertObjectHasProperty($item->type, $item); $this->assertEquals('keywords', $item->{$item->type}); $this->assertEquals($string, $item->content); } @@ -119,14 +114,14 @@ protected function executeOverloadPrepend(string $type): void for ($i = 0; $i < 3; ++$i) { $string .= ' foo'; $this->helper->$action('keywords', $string); - $values = $this->helper->getArrayCopy(); - $this->assertEquals($i + 1, count($values)); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount($i + 1, $values); $item = array_shift($values); - - $this->assertObjectHasAttribute('type', $item); - $this->assertObjectHasAttribute('modifiers', $item); - $this->assertObjectHasAttribute('content', $item); - $this->assertObjectHasAttribute($item->type, $item); + self::assertIsObject($item); + $this->assertObjectHasProperty('type', $item); + $this->assertObjectHasProperty('modifiers', $item); + $this->assertObjectHasProperty('content', $item); + $this->assertObjectHasProperty($item->type, $item); $this->assertEquals('keywords', $item->{$item->type}); $this->assertEquals($string, $item->content); } @@ -142,14 +137,16 @@ protected function executeOverloadSet(string $type): void $string .= ' foo'; } $this->helper->$setAction('keywords', $string); - $values = $this->helper->getArrayCopy(); + + $values = $this->helper->getContainer()->getArrayCopy(); $this->assertCount(1, $values); $item = array_shift($values); + self::assertIsObject($item); - $this->assertObjectHasAttribute('type', $item); - $this->assertObjectHasAttribute('modifiers', $item); - $this->assertObjectHasAttribute('content', $item); - $this->assertObjectHasAttribute($item->type, $item); + $this->assertObjectHasProperty('type', $item); + $this->assertObjectHasProperty('modifiers', $item); + $this->assertObjectHasProperty('content', $item); + $this->assertObjectHasProperty($item->type, $item); $this->assertEquals('keywords', $item->{$item->type}); $this->assertEquals($string, $item->content); } @@ -201,9 +198,9 @@ public function testOverloadingThrowsExceptionWithInvalidMethodType(): void public function testCanBuildMetaTagsWithAttributes(): void { $this->helper->setName('keywords', 'foo bar', ['lang' => 'us_en', 'scheme' => 'foo', 'bogus' => 'unused']); - $value = $this->helper->getValue(); - - $this->assertObjectHasAttribute('modifiers', $value); + $value = $this->helper->getContainer()->getValue(); + self::assertIsObject($value); + $this->assertObjectHasProperty('modifiers', $value); $modifiers = $value->modifiers; $this->assertArrayHasKey('lang', $modifiers); $this->assertEquals('us_en', $modifiers['lang']); @@ -227,31 +224,45 @@ public function testToStringReturnsValidHtml(): void $metas = substr_count($string, 'http-equiv="'); $this->assertEquals(1, $metas); - $attributeEscaper = $this->attributeEscaper; - $this->assertStringContainsString('http-equiv="screen" content="projection"', $string); - $this->assertStringContainsString('name="keywords" content="' . $attributeEscaper('foo bar') . '"', $string); + $this->assertStringContainsString( + 'name="keywords" content="' . $this->escaper->escapeHtmlAttr('foo bar') . '"', + $string, + ); $this->assertStringContainsString('lang="us_en"', $string); $this->assertStringContainsString('scheme="foo"', $string); $this->assertStringNotContainsString('bogus', $string); $this->assertStringNotContainsString('unused', $string); - $this->assertStringContainsString('name="title" content="' . $attributeEscaper('boo bah') . '"', $string); + $this->assertStringContainsString( + 'name="title" content="' . $this->escaper->escapeHtmlAttr('boo bah') . '"', + $string, + ); } public function testToStringWhenInvalidKeyProvidedShouldConvertThrownException(): void { $this->helper->__invoke('some-content', 'tag value', 'not allowed key'); - set_error_handler([$this, 'handleErrors']); - $string = @$this->helper->toString(); - $this->assertEquals('', $string); - $this->assertIsString($this->error); + $error = null; + set_error_handler(function (int $code, string $message) use (&$error): bool { + self::assertSame(E_USER_WARNING, $code); + $error = $message; + + return true; + }, E_USER_WARNING); + $string = $this->helper->toString(); + self::assertEquals('', $string); + self::assertEquals( + 'Invalid type "not allowed key" provided for meta', + $error, + ); + restore_error_handler(); } public function testHeadMetaHelperCreatesItemEntry(): void { $this->helper->__invoke('foo', 'keywords'); - $values = $this->helper->getArrayCopy(); - $this->assertEquals(1, count($values)); + $values = $this->helper->getContainer()->getArrayCopy(); + $this->assertCount(1, $values); $item = array_shift($values); $this->assertEquals('foo', $item->content); $this->assertEquals('name', $item->type); @@ -261,8 +272,8 @@ public function testHeadMetaHelperCreatesItemEntry(): void public function testOverloadingOffsetInsertsAtOffset(): void { $this->helper->offsetSetName(100, 'keywords', 'foo'); - $values = $this->helper->getArrayCopy(); - $this->assertEquals(1, count($values)); + $values = $this->helper->getContainer()->getArrayCopy(); + $this->assertCount(1, $values); $this->assertArrayHasKey(100, $values); $item = $values[100]; $this->assertEquals('foo', $item->content); @@ -288,36 +299,32 @@ public function testStringRepresentationReflectsDoctype(): void $test = $this->helper->toString(); - $attributeEscaper = $this->attributeEscaper; - $this->assertStringNotContainsString('/>', $test); - $this->assertStringContainsString($attributeEscaper('some content'), $test); + $this->assertStringContainsString($this->escaper->escapeHtmlAttr('some content'), $test); $this->assertStringContainsString('foo', $test); } public function testSetNameDoesntClobber(): void { - $view = new View(); - $view->plugin(HeadMeta::class)->setName('keywords', 'foo'); - $view->plugin(HeadMeta::class)->appendHttpEquiv('pragma', 'bar'); - $view->plugin(HeadMeta::class)->appendHttpEquiv('Cache-control', 'baz'); - $view->plugin(HeadMeta::class)->setName('keywords', 'bat'); + $this->helper->setName('keywords', 'foo'); + $this->helper->appendHttpEquiv('pragma', 'bar'); + $this->helper->appendHttpEquiv('Cache-control', 'baz'); + $this->helper->setName('keywords', 'bat'); $this->assertEquals( '' . PHP_EOL . '' . PHP_EOL . '', - $view->plugin(HeadMeta::class)->toString() + $this->helper->toString() ); } public function testSetNameDoesntClobberPart2(): void { - $view = new View(); - $view->plugin(HeadMeta::class)->setName('keywords', 'foo'); - $view->plugin(HeadMeta::class)->setName('description', 'foo'); - $view->plugin(HeadMeta::class)->appendHttpEquiv('pragma', 'baz'); - $view->plugin(HeadMeta::class)->appendHttpEquiv('Cache-control', 'baz'); - $view->plugin(HeadMeta::class)->setName('keywords', 'bar'); + $this->helper->setName('keywords', 'foo'); + $this->helper->setName('description', 'foo'); + $this->helper->appendHttpEquiv('pragma', 'baz'); + $this->helper->appendHttpEquiv('Cache-control', 'baz'); + $this->helper->setName('keywords', 'bar'); $expected = sprintf( '%1$s' @@ -327,14 +334,13 @@ public function testSetNameDoesntClobberPart2(): void PHP_EOL ); - $this->assertEquals($expected, $view->plugin(HeadMeta::class)->toString()); + $this->assertEquals($expected, $this->helper->toString()); } public function testPlacesMetaTagsInProperOrder(): void { - $view = new View(); - $view->plugin(HeadMeta::class)->setName('keywords', 'foo'); - $view->plugin(HeadMeta::class)->__invoke( + $this->helper->setName('keywords', 'foo'); + $this->helper->__invoke( 'some content', 'bar', 'name', @@ -342,15 +348,13 @@ public function testPlacesMetaTagsInProperOrder(): void Helper\Placeholder\Container\AbstractContainer::PREPEND ); - $attributeEscaper = $this->attributeEscaper; - $expected = sprintf( '%s' . '', - $attributeEscaper('some content'), + $this->escaper->escapeHtmlAttr('some content'), PHP_EOL ); - $this->assertEquals($expected, $view->plugin(HeadMeta::class)->toString()); + $this->assertEquals($expected, $this->helper->toString()); } public function testContainerMaintainsCorrectOrderOfItems(): void @@ -379,7 +383,7 @@ public function testCharsetValidateFail(): void $view->plugin(Doctype::class)->__invoke('HTML4_STRICT'); $this->expectException(Exception\ExceptionInterface::class); - $view->plugin(HeadMeta::class)->setCharset('utf-8'); + $this->helper->setCharset('utf-8'); } public function testCharset(): void @@ -387,17 +391,17 @@ public function testCharset(): void $view = new View(); $view->plugin(Doctype::class)->__invoke('HTML5'); - $view->plugin(HeadMeta::class)->setCharset('utf-8'); + $this->helper->setCharset('utf-8'); $this->assertEquals( '', - $view->plugin(HeadMeta::class)->toString() + $this->helper->toString() ); $view->plugin(Doctype::class)->__invoke('XHTML5'); $this->assertEquals( '', - $view->plugin(HeadMeta::class)->toString() + $this->helper->toString() ); } @@ -406,18 +410,18 @@ public function testCharsetPosition(): void $view = new View(); $view->plugin(Doctype::class)->__invoke('HTML5'); - $view->plugin(HeadMeta::class) + $this->helper ->setProperty('description', 'foobar') ->setCharset('utf-8'); $this->assertEquals( '' . PHP_EOL . '', - $view->plugin(HeadMeta::class)->toString() + $this->helper->toString() ); } - public function testCarsetWithXhtmlDoctypeGotException(): void + public function testCharsetWithXhtmlDoctypeGotException(): void { $this->expectException(Exception\InvalidArgumentException::class); $this->expectExceptionMessage('XHTML* doctype has no attribute charset; please use appendHttpEquiv()'); @@ -425,7 +429,7 @@ public function testCarsetWithXhtmlDoctypeGotException(): void $view = new View(); $view->plugin(Doctype::class)->__invoke('XHTML1_RDFA'); - $view->plugin(HeadMeta::class) + $this->helper ->setCharset('utf-8'); } @@ -434,9 +438,7 @@ public function testPropertyIsSupportedWithRdfaDoctype(): void $this->view->doctype('XHTML1_RDFA'); $this->helper->__invoke('foo', 'og:title', 'property'); - $attributeEscaper = $this->attributeEscaper; - - $expected = sprintf('', $attributeEscaper('og:title')); + $expected = sprintf('', $this->escaper->escapeHtmlAttr('og:title')); $this->assertEquals($expected, $this->helper->toString()); } @@ -482,9 +484,10 @@ public function testItempropIsSupportedWithHtml5Doctype(): void $this->view->doctype('HTML5'); $this->helper->__invoke('HeadMeta with Microdata', 'description', 'itemprop'); - $attributeEscaper = $this->attributeEscaper; - - $expected = sprintf('', $attributeEscaper('HeadMeta with Microdata')); + $expected = sprintf( + '', + $this->escaper->escapeHtmlAttr('HeadMeta with Microdata'), + ); $this->assertEquals($expected, $this->helper->toString()); } diff --git a/test/Helper/HeadScriptTest.php b/test/Helper/HeadScriptTest.php index 4a18089f7..40af08bb8 100644 --- a/test/Helper/HeadScriptTest.php +++ b/test/Helper/HeadScriptTest.php @@ -6,14 +6,15 @@ use DOMDocument; use Generator; +use Laminas\Escaper\Escaper; use Laminas\View; -use Laminas\View\Helper; use Laminas\View\Helper\Doctype; +use Laminas\View\Helper\HeadScript; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use function array_shift; use function assert; -use function count; use function sprintf; use function strtolower; use function substr_count; @@ -24,36 +25,26 @@ class HeadScriptTest extends TestCase { - /** @var Helper\HeadScript */ - public $helper; + private HeadScript $helper; + private Escaper $escaper; - /** @var Helper\EscapeHtmlAttr */ - public $attributeEscaper; - - /** @var string */ - public $basePath; - - /** - * Sets up the fixture, for example, open a network connection. - * This method is called before a test is executed. - */ protected function setUp(): void { - $this->basePath = __DIR__ . '/_files/modules'; - $this->helper = new Helper\HeadScript(); - $this->attributeEscaper = new Helper\EscapeHtmlAttr(); + $this->helper = new HeadScript(); + $this->escaper = new Escaper(); } public function testHeadScriptReturnsObjectInstance(): void { $placeholder = $this->helper->__invoke(); - $this->assertInstanceOf(Helper\HeadScript::class, $placeholder); + $this->assertInstanceOf(HeadScript::class, $placeholder); } public function testAppendThrowsExceptionWithInvalidArguments(): void { $this->expectException(View\Exception\InvalidArgumentException::class); $this->expectExceptionMessage('Invalid argument passed to append'); + /** @psalm-suppress InvalidArgument */ $this->helper->append('foo'); } @@ -61,6 +52,7 @@ public function testPrependThrowsExceptionWithInvalidArguments(): void { $this->expectException(View\Exception\InvalidArgumentException::class); $this->expectExceptionMessage('Invalid argument passed to prepend'); + /** @psalm-suppress InvalidArgument */ $this->helper->prepend('foo'); } @@ -68,6 +60,7 @@ public function testSetThrowsExceptionWithInvalidArguments(): void { $this->expectException(View\Exception\InvalidArgumentException::class); $this->expectExceptionMessage('Invalid argument passed to set'); + /** @psalm-suppress InvalidArgument */ $this->helper->set('foo'); } @@ -75,6 +68,7 @@ public function testOffsetSetThrowsExceptionWithInvalidArguments(): void { $this->expectException(View\Exception\InvalidArgumentException::class); $this->expectExceptionMessage('Invalid argument passed to offsetSet'); + /** @psalm-suppress InvalidArgument */ $this->helper->offsetSet(1, 'foo'); } @@ -90,14 +84,15 @@ private function executeOverloadAppend(string $type): void for ($i = 0; $i < 3; ++$i) { $string .= ' foo'; $this->helper->$action($string); - $values = $this->helper->getArrayCopy(); - $this->assertCount($i + 1, $values); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount($i + 1, $values); + $item = $values[$i]; if ('file' === $type) { - $this->assertEquals($string, $values[$i]->attributes['src']); + self::assertEquals($string, $item->attributes['src']); } elseif ('script' === $type) { - $this->assertEquals($string, $values[$i]->source); + self::assertEquals($string, $item->source); } - $this->assertEquals('text/javascript', $values[$i]->type); + self::assertEquals('text/javascript', $item->type); } } @@ -108,15 +103,16 @@ private function executeOverloadPrepend(string $type): void for ($i = 0; $i < 3; ++$i) { $string .= ' foo'; $this->helper->$action($string); - $values = $this->helper->getArrayCopy(); - $this->assertCount($i + 1, $values); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount($i + 1, $values); $first = array_shift($values); + self::assertIsObject($first); if ('file' === $type) { - $this->assertEquals($string, $first->attributes['src']); + self::assertEquals($string, $first->attributes['src']); } elseif ('script' === $type) { - $this->assertEquals($string, $first->source); + self::assertEquals($string, $first->source); } - $this->assertEquals('text/javascript', $first->type); + self::assertEquals('text/javascript', $first->type); } } @@ -129,14 +125,15 @@ private function executeOverloadSet(string $type): void $string .= ' foo'; } $this->helper->$action($string); - $values = $this->helper->getArrayCopy(); - $this->assertCount(1, $values); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount(1, $values); + $item = $values[0]; if ('file' === $type) { - $this->assertEquals($string, $values[0]->attributes['src']); + self::assertEquals($string, $item->attributes['src']); } elseif ('script' === $type) { - $this->assertEquals($string, $values[0]->source); + self::assertEquals($string, $item->source); } - $this->assertEquals('text/javascript', $values[0]->type); + self::assertEquals('text/javascript', $item->type); } private function executeOverloadOffsetSet(string $type): void @@ -144,14 +141,15 @@ private function executeOverloadOffsetSet(string $type): void $action = 'offsetSet' . $this->inflectAction($type); $string = 'foo'; $this->helper->$action(5, $string); - $values = $this->helper->getArrayCopy(); - $this->assertCount(1, $values); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount(1, $values); + $item = $values[5]; if ('file' === $type) { - $this->assertEquals($string, $values[5]->attributes['src']); + self::assertEquals($string, $item->attributes['src']); } elseif ('script' === $type) { - $this->assertEquals($string, $values[5]->source); + self::assertEquals($string, $item->source); } - $this->assertEquals('text/javascript', $values[5]->type); + self::assertEquals('text/javascript', $item->type); } public function testOverloadAppendFileAppendsScriptsToStack(): void @@ -223,21 +221,21 @@ public function testHeadScriptAppropriatelySetsScriptItems(): void $this->helper->__invoke('FILE', 'foo', 'set') ->__invoke('SCRIPT', 'bar', 'prepend') ->__invoke('SCRIPT', 'baz', 'append'); - $items = $this->helper->getArrayCopy(); + $items = $this->helper->getContainer()->getArrayCopy(); for ($i = 0; $i < 3; ++$i) { $item = $items[$i]; switch ($i) { case 0: - $this->assertObjectHasAttribute('source', $item); + $this->assertObjectHasProperty('source', $item); $this->assertEquals('bar', $item->source); break; case 1: - $this->assertObjectHasAttribute('attributes', $item); + $this->assertObjectHasProperty('attributes', $item); $this->assertTrue(isset($item->attributes['src'])); $this->assertEquals('foo', $item->attributes['src']); break; case 2: - $this->assertObjectHasAttribute('source', $item); + $this->assertObjectHasProperty('source', $item); $this->assertEquals('baz', $item->source); break; } @@ -276,8 +274,8 @@ public function testCapturingCapturesToObject(): void $this->helper->captureStart(); echo 'foobar'; $this->helper->captureEnd(); - $values = $this->helper->getArrayCopy(); - $this->assertEquals(1, count($values), var_export($values, true)); + $values = $this->helper->getContainer()->getArrayCopy(); + $this->assertCount(1, $values, var_export($values, true)); $item = array_shift($values); $this->assertStringContainsString('foobar', $item->source); } @@ -305,7 +303,7 @@ public function testDoesNotAllowDuplicateFiles(): void { $this->helper->__invoke('FILE', '/js/prototype.js'); $this->helper->__invoke('FILE', '/js/prototype.js'); - $this->assertEquals(1, count($this->helper)); + $this->assertCount(1, $this->helper); } public function testRenderingDoesNotRenderArbitraryAttributesByDefault(): void @@ -412,19 +410,17 @@ public function testContainerMaintainsCorrectOrderOfItems(): void $test = $this->helper->toString(); - $attributeEscaper = $this->attributeEscaper; - $expected = sprintf( '%1$s' . '%1$s' . '%1$s' . '', PHP_EOL, - $attributeEscaper('text/javascript'), - $attributeEscaper('test1.js'), - $attributeEscaper('test4.js'), - $attributeEscaper('test3.js'), - $attributeEscaper('test2.js') + $this->escaper->escapeHtmlAttr('text/javascript'), + $this->escaper->escapeHtmlAttr('test1.js'), + $this->escaper->escapeHtmlAttr('test4.js'), + $this->escaper->escapeHtmlAttr('test3.js'), + $this->escaper->escapeHtmlAttr('test2.js') ); $this->assertEquals($expected, $test); @@ -525,8 +521,8 @@ public function testSupportsNonceAttribute(): void ); } - /** @return Generator */ - public function booleanAttributeDataProvider(): Generator + /** @return Generator> */ + public static function booleanAttributeDataProvider(): Generator { $values = ['async', 'defer', 'nomodule']; @@ -535,7 +531,7 @@ public function booleanAttributeDataProvider(): Generator } } - /** @dataProvider booleanAttributeDataProvider */ + #[DataProvider('booleanAttributeDataProvider')] public function testBooleanAttributesUseTheKeyNameAsTheValue(string $attribute): void { ($this->helper)()->appendScript( @@ -550,7 +546,7 @@ public function testBooleanAttributesUseTheKeyNameAsTheValue(string $attribute): ); } - /** @dataProvider booleanAttributeDataProvider */ + #[DataProvider('booleanAttributeDataProvider')] public function testBooleanAttributesCanBeAppliedToModules(string $attribute): void { ($this->helper)()->appendScript( diff --git a/test/Helper/HeadStyleTest.php b/test/Helper/HeadStyleTest.php index df244fdfe..9646ea9f0 100644 --- a/test/Helper/HeadStyleTest.php +++ b/test/Helper/HeadStyleTest.php @@ -6,65 +6,59 @@ use DOMDocument; use Laminas\View; -use Laminas\View\Helper; +use Laminas\View\Exception\InvalidArgumentException; +use Laminas\View\Helper\HeadStyle; use PHPUnit\Framework\TestCase; use stdClass; use function array_shift; -use function count; use function substr_count; use const PHP_EOL; class HeadStyleTest extends TestCase { - /** @var Helper\HeadStyle */ - public $helper; + private HeadStyle $helper; - /** @var string */ - public $basePath; - - /** - * Sets up the fixture, for example, open a network connection. - * This method is called before a test is executed. - */ protected function setUp(): void { - $this->basePath = __DIR__ . '/_files/modules'; - $this->helper = new Helper\HeadStyle(); + $this->helper = new HeadStyle(); } - public function testHeadStyleReturnsObjectInstance(): void + public function testInvokeWithoutArgumentsReturnsSelf(): void { - $placeholder = $this->helper->__invoke(); - $this->assertInstanceOf(Helper\HeadStyle::class, $placeholder); + self::assertSame($this->helper, $this->helper->__invoke()); } public function testAppendThrowsExceptionGivenNonStyleArgument(): void { - $this->expectException(View\Exception\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid value passed to append'); + /** @psalm-suppress InvalidArgument */ $this->helper->append('foo'); } public function testPrependThrowsExceptionGivenNonStyleArgument(): void { - $this->expectException(View\Exception\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid value passed to prepend'); + /** @psalm-suppress InvalidArgument */ $this->helper->prepend('foo'); } public function testSetThrowsExceptionGivenNonStyleArgument(): void { - $this->expectException(View\Exception\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid value passed to set'); + /** @psalm-suppress InvalidArgument */ $this->helper->set('foo'); } public function testOffsetSetThrowsExceptionGivenNonStyleArgument(): void { - $this->expectException(View\Exception\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid value passed to offsetSet'); + /** @psalm-suppress InvalidArgument */ $this->helper->offsetSet(1, 'foo'); } @@ -74,14 +68,14 @@ public function testOverloadAppendStyleAppendsStyleToStack(): void for ($i = 0; $i < 3; ++$i) { $string .= PHP_EOL . 'a {}'; $this->helper->appendStyle($string); - $values = $this->helper->getArrayCopy(); - $this->assertEquals($i + 1, count($values)); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount($i + 1, $values); $item = $values[$i]; - $this->assertInstanceOf(stdClass::class, $item); - $this->assertObjectHasAttribute('content', $item); - $this->assertObjectHasAttribute('attributes', $item); - $this->assertEquals($string, $item->content); + self::assertInstanceOf(stdClass::class, $item); + self::assertObjectHasProperty('content', $item); + self::assertObjectHasProperty('attributes', $item); + self::assertEquals($string, $item->content); } } @@ -91,33 +85,34 @@ public function testOverloadPrependStylePrependsStyleToStack(): void for ($i = 0; $i < 3; ++$i) { $string .= PHP_EOL . 'a {}'; $this->helper->prependStyle($string); - $values = $this->helper->getArrayCopy(); - $this->assertEquals($i + 1, count($values)); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount($i + 1, $values); $item = array_shift($values); - $this->assertInstanceOf(stdClass::class, $item); - $this->assertObjectHasAttribute('content', $item); - $this->assertObjectHasAttribute('attributes', $item); - $this->assertEquals($string, $item->content); + self::assertInstanceOf(stdClass::class, $item); + self::assertObjectHasProperty('content', $item); + self::assertObjectHasProperty('attributes', $item); + self::assertEquals($string, $item->content); } } - public function testOverloadSetOversitesStack(): void + public function testOverloadSetOverwritesStack(): void { $string = 'a {}'; for ($i = 0; $i < 3; ++$i) { $this->helper->appendStyle($string); $string .= PHP_EOL . 'a {}'; } + $this->helper->setStyle($string); - $values = $this->helper->getArrayCopy(); - $this->assertEquals(1, count($values)); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount(1, $values); $item = array_shift($values); - $this->assertInstanceOf(stdClass::class, $item); - $this->assertObjectHasAttribute('content', $item); - $this->assertObjectHasAttribute('attributes', $item); - $this->assertEquals($string, $item->content); + self::assertInstanceOf(stdClass::class, $item); + self::assertObjectHasProperty('content', $item); + self::assertObjectHasProperty('attributes', $item); + self::assertEquals($string, $item->content); } public function testCanBuildStyleTagsWithAttributes(): void @@ -126,52 +121,66 @@ public function testCanBuildStyleTagsWithAttributes(): void 'lang' => 'us_en', 'title' => 'foo', 'media' => 'projection', - 'dir' => 'rtol', + 'dir' => 'rtl', 'bogus' => 'unused', ]); - $value = $this->helper->getValue(); - - $this->assertObjectHasAttribute('attributes', $value); + $value = $this->helper->getContainer()->getValue(); + self::assertIsObject($value); + self::assertObjectHasProperty('attributes', $value); $attributes = $value->attributes; - $this->assertTrue(isset($attributes['lang'])); - $this->assertTrue(isset($attributes['title'])); - $this->assertTrue(isset($attributes['media'])); - $this->assertTrue(isset($attributes['dir'])); - $this->assertTrue(isset($attributes['bogus'])); - $this->assertEquals('us_en', $attributes['lang']); - $this->assertEquals('foo', $attributes['title']); - $this->assertEquals('projection', $attributes['media']); - $this->assertEquals('rtol', $attributes['dir']); - $this->assertEquals('unused', $attributes['bogus']); + self::assertTrue(isset($attributes['lang'])); + self::assertTrue(isset($attributes['title'])); + self::assertTrue(isset($attributes['media'])); + self::assertTrue(isset($attributes['dir'])); + self::assertTrue(isset($attributes['bogus'])); + self::assertEquals('us_en', $attributes['lang']); + self::assertEquals('foo', $attributes['title']); + self::assertEquals('projection', $attributes['media']); + self::assertEquals('rtl', $attributes['dir']); + self::assertEquals('unused', $attributes['bogus']); } - public function testRenderedStyleTagsContainHtmlEscaping(): void + public function testRenderedStyleMarkupHasExpectedOutput(): void { $this->helper->setStyle('a {}', [ - 'lang' => 'us_en', + 'lang' => 'en_us', 'title' => 'foo', 'media' => 'screen', - 'dir' => 'rtol', + 'dir' => 'rtl', 'bogus' => 'unused', ]); - $value = $this->helper->toString(); - $this->assertStringContainsString('', $value); + + $expect = << + a {} + + HTML; + self::assertSame($expect, $this->helper->toString()); } public function testRenderedStyleTagsContainsDefaultMedia(): void { $this->helper->setStyle('a {}', []); $value = $this->helper->toString(); - $this->assertMatchesRegularExpression('#'); - $this->assertEquals(3, $styles); - $this->assertStringContainsString($style3, $html); - $this->assertStringContainsString($style2, $html); - $this->assertStringContainsString($style1, $html); + self::assertEquals(3, $styles); + self::assertStringContainsString($style3, $html); + self::assertStringContainsString($style2, $html); + self::assertStringContainsString($style1, $html); } public function testCapturingCapturesToObject(): void @@ -219,26 +228,30 @@ public function testCapturingCapturesToObject(): void $this->helper->captureStart(); echo 'foobar'; $this->helper->captureEnd(); - $values = $this->helper->getArrayCopy(); - $this->assertEquals(1, count($values)); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount(1, $values); $item = array_shift($values); - $this->assertStringContainsString('foobar', $item->content); + self::assertIsObject($item); + self::assertObjectHasProperty('content', $item); + self::assertStringContainsString('foobar', $item->content); } public function testOverloadingOffsetSetWritesToSpecifiedIndex(): void { $this->helper->offsetSetStyle(100, 'foobar'); - $values = $this->helper->getArrayCopy(); - $this->assertEquals(1, count($values)); - $this->assertTrue(isset($values[100])); + $values = $this->helper->getContainer()->getArrayCopy(); + self::assertCount(1, $values); + self::assertTrue(isset($values[100])); $item = $values[100]; - $this->assertStringContainsString('foobar', $item->content); + self::assertObjectHasProperty('content', $item); + self::assertStringContainsString('foobar', $item->content); } public function testInvalidMethodRaisesException(): void { $this->expectException(View\Exception\BadMethodCallException::class); $this->expectExceptionMessage('Method "bogusMethod" does not exist'); + /** @psalm-suppress UndefinedMagicMethod */ $this->helper->bogusMethod(); } @@ -250,27 +263,41 @@ public function testTooFewArgumentsRaisesException(): void $this->helper->appendStyle(); } - public function testIndentationIsHonored(): void + public function testThatEmptyStylesWillYieldAnEmptyValue(): void { - $this->helper->setIndent(4); - $this->helper->appendStyle(' -a { - display: none; -}'); - $this->helper->appendStyle(' -h1 { - font-weight: bold -}'); - $string = $this->helper->toString(); + $this->helper->appendStyle('', ['media' => 'screen']); + self::assertSame('', $this->helper->toString()); + } - $scripts = substr_count($string, ' assertEquals(2, $scripts); - $this->assertStringContainsString(' <', $test); - $this->assertStringContainsString('', $test); + self::assertStringContainsString('<', $test); + self::assertStringContainsString('', $test); } public function testConditionalScriptNoIEWidthSpace(): void @@ -361,8 +407,8 @@ public function testConditionalScriptNoIEWidthSpace(): void display: none; }', ['media' => 'screen,projection', 'conditional' => '! IE']); $test = $this->helper->toString(); - $this->assertStringContainsString('<', $test); - $this->assertStringContainsString('', $test); + self::assertStringContainsString('<', $test); + self::assertStringContainsString('', $test); } public function testContainerMaintainsCorrectOrderOfItems(): void @@ -374,18 +420,19 @@ public function testContainerMaintainsCorrectOrderOfItems(): void $this->helper->offsetSetStyle(5, $style2); $test = $this->helper->toString(); - $expected = '' . PHP_EOL - . ''; - - $this->assertEquals($expected, $test); + $expected = '' + . PHP_EOL + . ''; + + self::assertEquals($expected, $test); } public function testRenderConditionalCommentsShouldNotContainHtmlEscaping(): void @@ -396,7 +443,7 @@ public function testRenderConditionalCommentsShouldNotContainHtmlEscaping(): voi ]); $value = $this->helper->toString(); - $this->assertStringNotContainsString('', $value); + self::assertStringNotContainsString('', $value); } } diff --git a/test/Helper/HeadTitleTest.php b/test/Helper/HeadTitleTest.php index 9b19feaf6..759f4841c 100644 --- a/test/Helper/HeadTitleTest.php +++ b/test/Helper/HeadTitleTest.php @@ -5,64 +5,55 @@ namespace LaminasTest\View\Helper; use Laminas\I18n\Translator\Translator; -use Laminas\View\Helper; +use Laminas\View\Helper\HeadTitle; use PHPUnit\Framework\TestCase; class HeadTitleTest extends TestCase { - /** @var Helper\HeadTitle */ + /** @var HeadTitle */ public $helper; - /** @var string */ - public $basePath; - - /** - * Sets up the fixture, for example, open a network connection. - * This method is called before a test is executed. - */ protected function setUp(): void { - $this->basePath = __DIR__ . '/_files/modules'; - $this->helper = new Helper\HeadTitle(); + $this->helper = new HeadTitle(); } - public function testHeadTitleReturnsObjectInstance(): void + public function testInvokeWithNoArgumentsReturnsSelf(): void { - $placeholder = $this->helper->__invoke(); - $this->assertInstanceOf(Helper\HeadTitle::class, $placeholder); + self::assertSame($this->helper, $this->helper->__invoke()); } public function testCanSetTitleViaHeadTitle(): void { $placeholder = $this->helper->__invoke('Foo Bar', 'SET'); - $this->assertEquals('Foo Bar', $placeholder->renderTitle()); + self::assertEquals('Foo Bar', $placeholder->renderTitle()); } public function testToStringWrapsToTitleTag(): void { $placeholder = $this->helper->__invoke('Foo Bar', 'SET'); - $this->assertEquals('Foo Bar', $placeholder->toString()); + self::assertEquals('Foo Bar', $placeholder->toString()); } public function testCanAppendTitleViaHeadTitle(): void { $this->helper->__invoke('Foo'); - $placeholder = $this->helper->__invoke('Bar'); - $this->assertEquals('FooBar', $placeholder->renderTitle()); + $this->helper->__invoke('Bar'); + self::assertEquals('FooBar', $this->helper->renderTitle()); } public function testCanPrependTitleViaHeadTitle(): void { $this->helper->__invoke('Foo'); $placeholder = $this->helper->__invoke('Bar', 'PREPEND'); - $this->assertEquals('BarFoo', $placeholder->renderTitle()); + self::assertEquals('BarFoo', $placeholder->renderTitle()); } public function testReturnedPlaceholderRenderTitleContainsFullTitleElement(): void { $this->helper->__invoke('Foo'); - $placeholder = $this->helper->__invoke('Bar', 'APPEND')->setSeparator(' :: '); - $this->assertEquals('Foo :: Bar', $placeholder->renderTitle()); + $this->helper->__invoke('Bar', 'APPEND')->setSeparator(' :: '); + self::assertEquals('Foo :: Bar', $this->helper->renderTitle()); } public function testRenderTitleEscapesEntries(): void @@ -82,7 +73,7 @@ public function testRenderTitleEscapesSeparator(): void $this->assertStringNotContainsString('
', $string); $this->assertStringContainsString('Foo', $string); $this->assertStringContainsString('Bar', $string); - $this->assertStringContainsString('br /', $string); + $this->assertStringContainsString('<br />', $string); } public function testIndentationIsHonored(): void @@ -106,7 +97,7 @@ public function testAutoEscapeIsHonored(): void $this->assertEquals('Some Title ©right;', $this->helper->renderTitle()); } - public function testLaminas918(): void + public function testThatAPrefixAndPostfixCanBeApplied(): void { $this->helper->__invoke('Some Title'); $this->helper->setPrefix('Prefix: '); @@ -115,7 +106,7 @@ public function testLaminas918(): void $this->assertEquals('Prefix: Some Title :Postfix', $this->helper->renderTitle()); } - public function testLaminas577(): void + public function testThatPrefixAndPostfixAreEscapedProperly(): void { $this->helper->setAutoEscape(true); $this->helper->__invoke('Some Title'); @@ -171,7 +162,17 @@ public function testCanPrependTitlesUsingDefaultAttachOrder(): void public function testReturnTypeDefaultAttachOrder(): void { - $this->assertInstanceOf(Helper\HeadTitle::class, $this->helper->setDefaultAttachOrder('PREPEND')); + $this->assertInstanceOf(HeadTitle::class, $this->helper->setDefaultAttachOrder('PREPEND')); $this->assertEquals('PREPEND', $this->helper->getDefaultAttachOrder()); } + + public function testCommonMagicMethods(): void + { + $this->helper->set('a little'); + $this->helper->prepend('Mary had'); + $this->helper->append('lamb'); + $this->helper->setSeparator(' '); + + self::assertSame('Mary had a little lamb', (string) $this->helper); + } } diff --git a/test/Helper/Navigation/AbstractHelperTest.php b/test/Helper/Navigation/AbstractHelperTest.php index 885e69761..3d4e6ee4c 100644 --- a/test/Helper/Navigation/AbstractHelperTest.php +++ b/test/Helper/Navigation/AbstractHelperTest.php @@ -10,7 +10,7 @@ /** * @psalm-suppress MissingConstructor */ -class AbstractHelperTest extends AbstractTest +class AbstractHelperTest extends AbstractTestCase { /** * View helper diff --git a/test/Helper/Navigation/AbstractTest.php b/test/Helper/Navigation/AbstractTestCase.php similarity index 90% rename from test/Helper/Navigation/AbstractTest.php rename to test/Helper/Navigation/AbstractTestCase.php index 7870d222f..b0e7307bd 100644 --- a/test/Helper/Navigation/AbstractTest.php +++ b/test/Helper/Navigation/AbstractTestCase.php @@ -5,6 +5,8 @@ namespace LaminasTest\View\Helper\Navigation; use Laminas\I18n\Translator\Translator; +use Laminas\ModuleManager\ModuleManager; +use Laminas\Mvc\Application; use Laminas\Mvc\Service\ServiceManagerConfig; use Laminas\Navigation\Navigation; use Laminas\Navigation\Service\DefaultNavigationFactory; @@ -30,7 +32,7 @@ * * @psalm-suppress MissingConstructor */ -abstract class AbstractTest extends TestCase +abstract class AbstractTestCase extends TestCase { /** @var ServiceManager */ protected $serviceManager; @@ -136,17 +138,19 @@ protected function setUp(): void } $sm->setService('ApplicationConfig', $smConfig); - $sm->get('ModuleManager')->loadModules(); - $sm->get('Application')->bootstrap(); + $moduleManager = $sm->get('ModuleManager'); + self::assertInstanceOf(ModuleManager::class, $moduleManager); + $moduleManager->loadModules(); + $application = $sm->get('Application'); + self::assertInstanceOf(Application::class, $application); + $application->bootstrap(); $sm->setFactory('Navigation', DefaultNavigationFactory::class); $sm->setService('nav1', $this->nav1); $sm->setService('nav2', $this->nav2); $sm->setAllowOverride(false); - - $app = $this->serviceManager->get('Application'); - $app->getMvcEvent()->setRouteMatch(new RouteMatch([ + $application->getMvcEvent()->setRouteMatch(new RouteMatch([ 'controller' => 'post', 'action' => 'view', 'id' => '1337', @@ -175,7 +179,7 @@ protected function getAcl(): array $acl->addResource(new GenericResource('guest_foo')); $acl->addResource(new GenericResource('member_foo'), 'guest_foo'); - $acl->addResource(new GenericResource('admin_foo', 'member_foo')); + $acl->addResource(new GenericResource('admin_foo')); $acl->addResource(new GenericResource('special_foo'), 'member_foo'); $acl->allow('guest', 'guest_foo'); @@ -201,7 +205,7 @@ protected function getTranslator(): Translator ]; $translator = new Translator(); $translator->getPluginManager()->setService('default', $loader); - $translator->addTranslationFile('default', null); + $translator->addTranslationFile('default', __FILE__); return $translator; } @@ -230,8 +234,8 @@ protected function getTranslatorWithTextDomain(): Translator $translator = new Translator(); $translator->getPluginManager()->setService('default1', $loader1); $translator->getPluginManager()->setService('default2', $loader2); - $translator->addTranslationFile('default1', null, 'LaminasTest_1'); - $translator->addTranslationFile('default2', null, 'LaminasTest_2'); + $translator->addTranslationFile('default1', __FILE__, 'LaminasTest_1'); + $translator->addTranslationFile('default2', __FILE__, 'LaminasTest_2'); return $translator; } } diff --git a/test/Helper/Navigation/BreadcrumbsTest.php b/test/Helper/Navigation/BreadcrumbsTest.php index 086f54a06..539b5317c 100644 --- a/test/Helper/Navigation/BreadcrumbsTest.php +++ b/test/Helper/Navigation/BreadcrumbsTest.php @@ -13,7 +13,7 @@ use function substr; use function trim; -class BreadcrumbsTest extends AbstractTest +class BreadcrumbsTest extends AbstractTestCase { /** * View helper. diff --git a/test/Helper/Navigation/LinksTest.php b/test/Helper/Navigation/LinksTest.php index 5a1e830e0..72438e7a6 100644 --- a/test/Helper/Navigation/LinksTest.php +++ b/test/Helper/Navigation/LinksTest.php @@ -27,7 +27,7 @@ /** * @psalm-suppress MissingConstructor */ -class LinksTest extends AbstractTest +class LinksTest extends AbstractTestCase { /** * View helper diff --git a/test/Helper/Navigation/MenuTest.php b/test/Helper/Navigation/MenuTest.php index 797aa0e14..0d8994317 100644 --- a/test/Helper/Navigation/MenuTest.php +++ b/test/Helper/Navigation/MenuTest.php @@ -20,7 +20,7 @@ /** * @psalm-suppress MissingConstructor */ -class MenuTest extends AbstractTest +class MenuTest extends AbstractTestCase { /** * View helper. diff --git a/test/Helper/Navigation/NavigationTest.php b/test/Helper/Navigation/NavigationTest.php index 2ce626115..0144a7021 100644 --- a/test/Helper/Navigation/NavigationTest.php +++ b/test/Helper/Navigation/NavigationTest.php @@ -29,7 +29,7 @@ /** * @psalm-suppress MissingConstructor */ -class NavigationTest extends AbstractTest +class NavigationTest extends AbstractTestCase { /** * View helper diff --git a/test/Helper/Navigation/SitemapTest.php b/test/Helper/Navigation/SitemapTest.php index f6843c84d..9e84b6aca 100644 --- a/test/Helper/Navigation/SitemapTest.php +++ b/test/Helper/Navigation/SitemapTest.php @@ -8,6 +8,7 @@ use Laminas\View; use Laminas\View\Helper\BasePath; use Laminas\View\Helper\Navigation\Sitemap; +use PHPUnit\Framework\Attributes\DataProvider; use Throwable; // phpcs:ignore use function count; @@ -19,7 +20,7 @@ /** * @psalm-suppress MissingConstructor */ -class SitemapTest extends AbstractTest +class SitemapTest extends AbstractTestCase { /** @var array */ private array $oldServer = []; @@ -206,7 +207,7 @@ public function testDisablingValidators(): void } /** @return array, 2:string}> */ - public function invalidServerUrlDataProvider(): array + public static function invalidServerUrlDataProvider(): array { return [ 'muppets' => [ @@ -217,10 +218,8 @@ public function invalidServerUrlDataProvider(): array ]; } - /** - * @param class-string $expectedType - * @dataProvider invalidServerUrlDataProvider - */ + /** @param class-string $expectedType */ + #[DataProvider('invalidServerUrlDataProvider')] public function testSetServerUrlRequiresValidUri( string $invalidServerUrl, string $expectedType, diff --git a/test/Helper/PartialLoopTest.php b/test/Helper/PartialLoopTest.php index 45a3978c9..32f7a1181 100644 --- a/test/Helper/PartialLoopTest.php +++ b/test/Helper/PartialLoopTest.php @@ -59,7 +59,7 @@ public function testPartialLoopIteratesOverIterator(): void ['message' => 'baz'], ['message' => 'bat'], ]; - $o = new TestAsset\IteratorTest($data); + $o = new TestAsset\PartialLoopIterator($data); $view = new View(); $view->resolver()->addPath($this->basePath . '/application/views/scripts'); @@ -74,12 +74,12 @@ public function testPartialLoopIteratesOverIterator(): void public function testPartialLoopIteratesOverRecursiveIterator(): void { - $rIterator = new TestAsset\RecursiveIteratorTest(); + $rIterator = new TestAsset\PartialLoopRecursiveIterator(); for ($i = 0; $i < 5; ++$i) { $data = [ 'message' => 'foo' . $i, ]; - $rIterator->addItem(new TestAsset\IteratorTest($data)); + $rIterator->addItem(new TestAsset\PartialLoopIterator($data)); } $view = new View(); @@ -88,7 +88,7 @@ public function testPartialLoopIteratesOverRecursiveIterator(): void $result = $this->helper->__invoke('partialLoop.phtml', $rIterator); foreach ($rIterator as $item) { - foreach ($item as $key => $value) { + foreach ($item as $value) { $this->assertStringContainsString($value, $result, var_export($value, true)); } } @@ -96,21 +96,14 @@ public function testPartialLoopIteratesOverRecursiveIterator(): void public function testPartialLoopThrowsExceptionWithBadIterator(): void { - $data = [ - ['message' => 'foo'], - ['message' => 'bar'], - ['message' => 'baz'], - ['message' => 'bat'], - ]; - $o = new TestAsset\BogusIteratorTest($data); - $view = new View(); $view->resolver()->addPath($this->basePath . '/application/views/scripts'); $this->helper->setView($view); $this->expectException(Exception\InvalidArgumentException::class); $this->expectExceptionMessage('PartialLoop helper requires iterable data'); - $this->helper->__invoke('partialLoop.phtml', $o); + /** @psalm-suppress InvalidArgument */ + $this->helper->__invoke('partialLoop.phtml', new TestAsset\PartialLoopBogusIterator()); } public function testPassingNullDataThrowsException(): void @@ -158,7 +151,7 @@ public function testShouldAllowIteratingOverObjectsImplementingToArray(): void ['message' => 'baz'], ['message' => 'bat'], ]; - $o = new TestAsset\ToArrayTest($data); + $o = new TestAsset\PartialLoopToArrayImplementor($data); $view = new View(); $view->resolver()->addPath($this->basePath . '/application/views/scripts'); @@ -179,7 +172,7 @@ public function testShouldNotCastToArrayIfObjectIsTraversable(): void new TestAsset\IteratorWithToArrayTestContainer(['message' => 'baz']), new TestAsset\IteratorWithToArrayTestContainer(['message' => 'bat']), ]; - $o = new TestAsset\IteratorWithToArrayTest($data); + $o = new TestAsset\PartialLoopIteratorWithToArray($data); $view = new View(); $view->resolver()->addPath($this->basePath . '/application/views/scripts'); @@ -242,12 +235,12 @@ public function testPartialLoopPartialCounterResets(): void public function testShouldNotConvertToArrayRecursivelyIfModelIsTraversable(): void { - $rIterator = new TestAsset\RecursiveIteratorTest(); + $rIterator = new TestAsset\PartialLoopRecursiveIterator(); for ($i = 0; $i < 5; ++$i) { $data = [ 'message' => 'foo' . $i, ]; - $rIterator->addItem(new TestAsset\IteratorTest($data)); + $rIterator->addItem(new TestAsset\PartialLoopIterator($data)); } $view = new View(); @@ -360,7 +353,7 @@ public function testPartialLoopIteratesOverIteratorInLoopMethod(): void ['message' => 'baz'], ['message' => 'bat'], ]; - $o = new TestAsset\IteratorTest($data); + $o = new TestAsset\PartialLoopIterator($data); $view = new View(); $view->resolver()->addPath($this->basePath . '/application/views/scripts'); @@ -375,12 +368,12 @@ public function testPartialLoopIteratesOverIteratorInLoopMethod(): void public function testPartialLoopIteratesOverRecursiveIteratorInLoopMethod(): void { - $rIterator = new TestAsset\RecursiveIteratorTest(); + $rIterator = new TestAsset\PartialLoopRecursiveIterator(); for ($i = 0; $i < 5; ++$i) { $data = [ 'message' => 'foo' . $i, ]; - $rIterator->addItem(new TestAsset\IteratorTest($data)); + $rIterator->addItem(new TestAsset\PartialLoopIterator($data)); } $view = new View(); @@ -397,20 +390,13 @@ public function testPartialLoopIteratesOverRecursiveIteratorInLoopMethod(): void public function testPartialLoopThrowsExceptionWithBadIteratorInLoopMethod(): void { - $data = [ - ['message' => 'foo'], - ['message' => 'bar'], - ['message' => 'baz'], - ['message' => 'bat'], - ]; - $o = new TestAsset\BogusIteratorTest($data); - $view = new View(); $view->resolver()->addPath($this->basePath . '/application/views/scripts'); $this->helper->setView($view); $this->expectException(Exception\InvalidArgumentException::class); $this->expectExceptionMessage('PartialLoop helper requires iterable data'); - $this->helper->Loop('partialLoop.phtml', $o); + /** @psalm-suppress InvalidArgument */ + $this->helper->Loop('partialLoop.phtml', new TestAsset\PartialLoopBogusIterator()); } public function testPassingNullDataThrowsExceptionInLoopMethod(): void @@ -452,7 +438,7 @@ public function testShouldAllowIteratingOverObjectsImplementingToArrayInLoopMeth ['message' => 'baz'], ['message' => 'bat'], ]; - $o = new TestAsset\ToArrayTest($data); + $o = new TestAsset\PartialLoopToArrayImplementor($data); $view = new View(); $view->resolver()->addPath($this->basePath . '/application/views/scripts'); @@ -473,7 +459,7 @@ public function testShouldNotCastToArrayIfObjectIsTraversableInLoopMethod(): voi new TestAsset\IteratorWithToArrayTestContainer(['message' => 'baz']), new TestAsset\IteratorWithToArrayTestContainer(['message' => 'bat']), ]; - $o = new TestAsset\IteratorWithToArrayTest($data); + $o = new TestAsset\PartialLoopIteratorWithToArray($data); $view = new View(); $view->resolver()->addPath($this->basePath . '/application/views/scripts'); @@ -536,12 +522,12 @@ public function testPartialLoopPartialCounterResetsInLoopMethod(): void public function testShouldNotConvertToArrayRecursivelyIfModelIsTraversableInLoopMethod(): void { - $rIterator = new TestAsset\RecursiveIteratorTest(); + $rIterator = new TestAsset\PartialLoopRecursiveIterator(); for ($i = 0; $i < 5; ++$i) { $data = [ 'message' => 'foo' . $i, ]; - $rIterator->addItem(new TestAsset\IteratorTest($data)); + $rIterator->addItem(new TestAsset\PartialLoopIterator($data)); } $view = new View(); diff --git a/test/Helper/Placeholder/ContainerTest.php b/test/Helper/Placeholder/ContainerTest.php index 02468897d..0ee42055b 100644 --- a/test/Helper/Placeholder/ContainerTest.php +++ b/test/Helper/Placeholder/ContainerTest.php @@ -5,8 +5,10 @@ namespace LaminasTest\View\Helper\Placeholder; use Exception; -use Laminas\View\Helper\Placeholder\Container as PlaceholderContainer; +use Laminas\View\Helper\Placeholder\Container; +use LaminasTest\View\Helper\TestAsset\NonStringableObject; use PHPUnit\Framework\TestCase; +use Throwable; use function array_keys; use function array_pop; @@ -20,8 +22,8 @@ class ContainerTest extends TestCase { - /** @var PlaceholderContainer */ - public $container; + /** @var Container */ + private Container $container; /** * Sets up the fixture, for example, open a network connection. @@ -29,7 +31,9 @@ class ContainerTest extends TestCase */ protected function setUp(): void { - $this->container = new PlaceholderContainer(); + /** @var Container $container */ + $container = new Container(); + $this->container = $container; } public function testSetSetsASingleValue(): void @@ -136,16 +140,18 @@ public function testCapturingToPlaceholderStoresContent(): void $this->container->captureStart(); echo 'This is content intended for capture'; $this->container->captureEnd(); + $value = $this->container->getValue(); + self::assertIsString($value); $this->assertStringContainsString( 'This is content intended for capture', - (string) $this->container->getValue() + $value, ); } public function testCapturingToPlaceholderAppendsContent(): void { - $this->container[] = 'foo'; - $originalCount = count($this->container); + $this->container->append('foo'); + $originalCount = count($this->container); $this->container->captureStart(); echo 'This is content intended for capture'; @@ -161,14 +167,14 @@ public function testCapturingToPlaceholderAppendsContent(): void $this->assertEquals('foo', $value[$lastIndex - 1]); $this->assertStringContainsString( 'This is content intended for capture', - (string) $value[$lastIndex] + $value[$lastIndex] ); } public function testCapturingToPlaceholderUsingPrependPrependsContent(): void { - $this->container[] = 'foo'; - $originalCount = count($this->container); + $this->container->append('foo'); + $originalCount = count($this->container); $this->container->captureStart('PREPEND'); echo 'This is content intended for capture'; @@ -182,21 +188,23 @@ public function testCapturingToPlaceholderUsingPrependPrependsContent(): void $lastIndex = array_pop($keys); assert(is_int($lastIndex)); $this->assertEquals('foo', $value[$lastIndex]); - $this->assertStringContainsString('This is content intended for capture', (string) $value[$lastIndex - 1]); + $this->assertStringContainsString('This is content intended for capture', $value[$lastIndex - 1]); } public function testCapturingToPlaceholderUsingSetOverwritesContent(): void { - $this->container[] = 'foo'; + $this->container->append('foo'); $this->container->captureStart('SET'); echo 'This is content intended for capture'; $this->container->captureEnd(); $this->assertCount(1, $this->container); + $value = $this->container->getValue(); + self::assertIsString($value); $this->assertStringContainsString( 'This is content intended for capture', - (string) $this->container->getValue() + $value ); } @@ -210,7 +218,7 @@ public function testCapturingToPlaceholderKeyUsingSetCapturesContent(): void $this->assertTrue(isset($this->container['key'])); $this->assertStringContainsString( 'This is content intended for capture', - (string) $this->container['key'] + $this->container['key'] ); } @@ -223,7 +231,7 @@ public function testCapturingToPlaceholderKeyUsingSetReplacesContentAtKey(): voi $this->assertCount(1, $this->container); $this->assertTrue(isset($this->container['key'])); - $value = (string) $this->container['key']; + $value = $this->container['key']; $this->assertStringContainsString('This is content intended for capture', $value); } @@ -236,20 +244,20 @@ public function testCapturingToPlaceholderKeyUsingAppendAppendsContentAtKey(): v $this->assertCount(1, $this->container); $this->assertTrue(isset($this->container['key'])); - $value = (string) $this->container['key']; + $value = $this->container['key']; $this->assertStringContainsString('Foobar This is content intended for capture', $value); } public function testNestedCapturesThrowsException(): void { - $this->container[] = 'foo'; - $caught = false; + $this->container->append('foo'); + $caught = false; try { $this->container->captureStart('SET'); $this->container->captureStart('SET'); $this->container->captureEnd(); $this->container->captureEnd(); - } catch (Exception $e) { + } catch (Exception) { $this->container->captureEnd(); $caught = true; } @@ -275,18 +283,18 @@ public function testToStringWithModifiersAndSingleValueReturnsFormattedValue(): public function testToStringWithNoModifiersAndCollectionReturnsImplodedString(): void { - $this->container[] = 'foo'; - $this->container[] = 'bar'; - $this->container[] = 'baz'; - $value = $this->container->toString(); + $this->container->append('foo'); + $this->container->append('bar'); + $this->container->append('baz'); + $value = $this->container->toString(); $this->assertEquals('foobarbaz', $value); } public function testToStringWithModifiersAndCollectionReturnsFormattedString(): void { - $this->container[] = 'foo'; - $this->container[] = 'bar'; - $this->container[] = 'baz'; + $this->container->append('foo'); + $this->container->append('bar'); + $this->container->append('baz'); $this->container->setPrefix('
  • ') ->setSeparator('
  • ') ->setPostfix('
'); @@ -296,9 +304,9 @@ public function testToStringWithModifiersAndCollectionReturnsFormattedString(): public function testToStringWithModifiersAndCollectionReturnsFormattedStringWithIndentation(): void { - $this->container[] = 'foo'; - $this->container[] = 'bar'; - $this->container[] = 'baz'; + $this->container->append('foo'); + $this->container->append('bar'); + $this->container->append('baz'); $this->container->setPrefix('
  • ') ->setSeparator('
  • ' . PHP_EOL . '
  • ') ->setPostfix('
') @@ -310,9 +318,9 @@ public function testToStringWithModifiersAndCollectionReturnsFormattedStringWith public function testToStringProxiesToToString(): void { - $this->container[] = 'foo'; - $this->container[] = 'bar'; - $this->container[] = 'baz'; + $this->container->append('foo'); + $this->container->append('bar'); + $this->container->append('baz'); $this->container->setPrefix('
  • ') ->setSeparator('
  • ') ->setPostfix('
'); @@ -320,6 +328,18 @@ public function testToStringProxiesToToString(): void $this->assertEquals('
  • foo
  • bar
  • baz
', $value); } + public function testThatToStringBehaviourForNonStringableElementsWillCauseErrors(): void + { + $container = new Container(); + $container->append(new NonStringableObject()); + try { + $container->toString(); + self::fail('An exception was not thrown'); + } catch (Throwable $e) { + self::assertStringContainsString('could not be converted to string', $e->getMessage()); + } + } + public function testPrependPushesValueToTopOfContainer(): void { $this->container['foo'] = 'bar'; diff --git a/test/Helper/Placeholder/StandaloneContainerTest.php b/test/Helper/Placeholder/StandaloneContainerTest.php index ba410090b..0494c0339 100644 --- a/test/Helper/Placeholder/StandaloneContainerTest.php +++ b/test/Helper/Placeholder/StandaloneContainerTest.php @@ -7,6 +7,7 @@ use Laminas\View\Exception\DomainException; use Laminas\View\Exception\InvalidArgumentException; use Laminas\View\Helper\Placeholder\Container; +use Laminas\View\Helper\Placeholder\Container\AbstractContainer; use Laminas\View\Renderer\PhpRenderer as View; use LaminasTest\View\Helper\TestAsset\Bar; use LaminasTest\View\Helper\TestAsset\Foo; @@ -14,8 +15,7 @@ class StandaloneContainerTest extends TestCase { - /** @var Foo */ - protected $helper; + private Foo $helper; /** * Sets up the fixture, for example, open a network connection. @@ -37,14 +37,14 @@ public function testSetContainer(): void public function testGetContainer(): void { $container = $this->helper->getContainer(); - $this->assertInstanceOf(Container::class, $container); + $this->assertInstanceOf(AbstractContainer::class, $container); } public function testGetContainerCreatesNewContainer(): void { $this->helper->deleteContainer(); $container = $this->helper->getContainer(); - $this->assertInstanceOf(Container::class, $container); + $this->assertInstanceOf(AbstractContainer::class, $container); } public function testDeleteContainer(): void @@ -57,12 +57,14 @@ public function testDeleteContainer(): void public function testSetContainerClassThrowsDomainException(): void { $this->expectException(DomainException::class); - $this->helper->setContainerClass('bat'); + /** @psalm-suppress UndefinedClass, ArgumentTypeCoercion */ + $this->helper->setContainerClass('not-a-known-class'); } public function testSetContainerClassThrowsInvalidArgumentException(): void { $this->expectException(InvalidArgumentException::class); + /** @psalm-suppress InvalidArgument */ $this->helper->setContainerClass(static::class); } @@ -82,11 +84,11 @@ public function testViewAccessorWorks(): void public function testContainerDoesNotPersistBetweenInstances(): void { $foo1 = new Foo(); - $foo1->append('Foo'); + $foo1->getContainer()->append('Foo'); $foo1->setSeparator(' - '); $foo2 = new Foo(); - $foo2->append('Bar'); + $foo2->getContainer()->append('Bar'); $test = $foo2->toString(); $this->assertStringNotContainsString('Foo', $test); diff --git a/test/Helper/Service/AssetFactoryTest.php b/test/Helper/Service/AssetFactoryTest.php index 1f07ee356..307e2d81f 100644 --- a/test/Helper/Service/AssetFactoryTest.php +++ b/test/Helper/Service/AssetFactoryTest.php @@ -7,6 +7,7 @@ use Laminas\View\Exception\RuntimeException; use Laminas\View\Helper\Asset; use Laminas\View\Helper\Service\AssetFactory; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; @@ -43,7 +44,7 @@ public function testThatAnExceptionWillBeThrownWhenTheResourceMapIsSetToANonArra /** * @return array}> */ - public function validConfigProvider(): array + public static function validConfigProvider(): array { return [ 'No View Helper Configuration' => [ @@ -85,10 +86,8 @@ public function validConfigProvider(): array ]; } - /** - * @dataProvider validConfigProvider - * @param array $config - */ + /** @param array $config */ + #[DataProvider('validConfigProvider')] public function testThatAnExceptionWillNotBeThrownWhenGivenUnsetOrEmptyArrayConfiguration(array $config): void { $container = $this->getServices($config); diff --git a/test/Helper/Service/BasePathFactoryTest.php b/test/Helper/Service/BasePathFactoryTest.php index 708137079..b93e3b3e5 100644 --- a/test/Helper/Service/BasePathFactoryTest.php +++ b/test/Helper/Service/BasePathFactoryTest.php @@ -8,6 +8,7 @@ use Laminas\View\Helper\BasePath; use Laminas\View\Helper\Service\BasePathFactory; use Laminas\View\HelperPluginManager; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class BasePathFactoryTest extends TestCase @@ -21,7 +22,7 @@ protected function setUp(): void } /** @return array */ - public function configDataProvider(): array + public static function configDataProvider(): array { return [ 'Empty Config' => [[]], @@ -31,7 +32,7 @@ public function configDataProvider(): array ]; } - /** @dataProvider configDataProvider */ + #[DataProvider('configDataProvider')] public function testFactoryWithVariousConfigurationSetups(array $config): void { $this->container->setService('config', $config); diff --git a/test/Helper/Service/IdentityFactoryTest.php b/test/Helper/Service/IdentityFactoryTest.php index e8685ccb0..27c782ea0 100644 --- a/test/Helper/Service/IdentityFactoryTest.php +++ b/test/Helper/Service/IdentityFactoryTest.php @@ -27,10 +27,15 @@ public function testFactoryReturnsEmptyIdentityIfNoAuthenticationServicePresent( { $this->services->expects(self::exactly(2)) ->method('has') - ->withConsecutive( - [AuthenticationService::class], - [AuthenticationServiceInterface::class] - )->willReturn(false); + ->with(self::callback(static function (string $serviceName): bool { + self::assertTrue( + $serviceName === AuthenticationService::class + || + $serviceName === AuthenticationServiceInterface::class + ); + + return true; + }))->willReturn(false); $factory = new IdentityFactory(); diff --git a/test/Helper/TestAsset/Bar.php b/test/Helper/TestAsset/Bar.php index 6a233f51a..599558f84 100644 --- a/test/Helper/TestAsset/Bar.php +++ b/test/Helper/TestAsset/Bar.php @@ -6,6 +6,7 @@ use Laminas\View\Helper\Placeholder\Container\AbstractContainer; +/** @extends AbstractContainer */ class Bar extends AbstractContainer { } diff --git a/test/Helper/TestAsset/Foo.php b/test/Helper/TestAsset/Foo.php index c9a9332ba..24968fab6 100644 --- a/test/Helper/TestAsset/Foo.php +++ b/test/Helper/TestAsset/Foo.php @@ -6,6 +6,7 @@ use Laminas\View\Helper\Placeholder\Container\AbstractStandalone; +/** @extends AbstractStandalone */ class Foo extends AbstractStandalone { } diff --git a/test/Helper/TestAsset/MockContainer.php b/test/Helper/TestAsset/MockContainer.php index 39819d984..e25bad837 100644 --- a/test/Helper/TestAsset/MockContainer.php +++ b/test/Helper/TestAsset/MockContainer.php @@ -5,7 +5,15 @@ namespace LaminasTest\View\Helper\TestAsset; use Laminas\View\Helper\Placeholder\Container\AbstractContainer; +use LaminasTest\View\Helper\Placeholder\RegistryTest; +/** + * @deprecated Should be removed in 3.0 when RegistryTest is removed + * + * @see RegistryTest + * + * @psalm-suppress MissingTemplateParam + */ class MockContainer extends AbstractContainer { /** @var array */ diff --git a/test/Helper/TestAsset/NonStringableObject.php b/test/Helper/TestAsset/NonStringableObject.php new file mode 100644 index 000000000..635c9ed43 --- /dev/null +++ b/test/Helper/TestAsset/NonStringableObject.php @@ -0,0 +1,9 @@ + */ -class IteratorTest implements Iterator +class PartialLoopIterator implements Iterator { /** @var array */ - public $items; + public array $items; /** @param array $array */ public function __construct(array $array) @@ -27,7 +28,7 @@ public function __construct(array $array) } /** - * @return T|false + * @return T|null */ #[ReturnTypeWillChange] public function current() diff --git a/test/Helper/TestAsset/IteratorWithToArrayTest.php b/test/Helper/TestAsset/PartialLoopIteratorWithToArray.php similarity index 84% rename from test/Helper/TestAsset/IteratorWithToArrayTest.php rename to test/Helper/TestAsset/PartialLoopIteratorWithToArray.php index 7453c4629..c35fb58ab 100644 --- a/test/Helper/TestAsset/IteratorWithToArrayTest.php +++ b/test/Helper/TestAsset/PartialLoopIteratorWithToArray.php @@ -14,11 +14,12 @@ /** * @template T + * @implements Iterator */ -class IteratorWithToArrayTest implements Iterator +class PartialLoopIteratorWithToArray implements Iterator { /** @var array */ - public $items; + public array $items; /** @param array $array */ public function __construct(array $array) @@ -33,7 +34,7 @@ public function toArray(): array } /** - * @return T|false + * @return T */ #[ReturnTypeWillChange] public function current() @@ -41,11 +42,7 @@ public function current() return current($this->items); } - /** - * @return array-key|null - */ - #[ReturnTypeWillChange] - public function key() + public function key(): int|string { return key($this->items); } diff --git a/test/Helper/TestAsset/RecursiveIteratorTest.php b/test/Helper/TestAsset/PartialLoopRecursiveIterator.php similarity index 58% rename from test/Helper/TestAsset/RecursiveIteratorTest.php rename to test/Helper/TestAsset/PartialLoopRecursiveIterator.php index 028ccc03e..585276a7e 100644 --- a/test/Helper/TestAsset/RecursiveIteratorTest.php +++ b/test/Helper/TestAsset/PartialLoopRecursiveIterator.php @@ -5,61 +5,48 @@ namespace LaminasTest\View\Helper\TestAsset; use Iterator; -use ReturnTypeWillChange; // phpcs:ignore use function current; use function key; use function next; use function reset; -class RecursiveIteratorTest implements Iterator +/** @implements Iterator */ +class PartialLoopRecursiveIterator implements Iterator { /** @var array */ - public $items; + public array $items; public function __construct() { $this->items = []; } - /** - * @return $this - */ - public function addItem(Iterator $iterator): self + public function addItem(Iterator $iterator): void { $this->items[] = $iterator; - return $this; } - /** @return Iterator|false */ - #[ReturnTypeWillChange] - public function current() + public function current(): Iterator { return current($this->items); } - /** - * @return array-key|null - */ - #[ReturnTypeWillChange] - public function key() + public function key(): int|string { return key($this->items); } - #[ReturnTypeWillChange] public function next(): void { next($this->items); } - #[ReturnTypeWillChange] public function rewind(): void { reset($this->items); } - #[ReturnTypeWillChange] public function valid(): bool { return current($this->items) !== false; diff --git a/test/Helper/TestAsset/ToArrayTest.php b/test/Helper/TestAsset/PartialLoopToArrayImplementor.php similarity index 88% rename from test/Helper/TestAsset/ToArrayTest.php rename to test/Helper/TestAsset/PartialLoopToArrayImplementor.php index 704a87394..48dbaa22b 100644 --- a/test/Helper/TestAsset/ToArrayTest.php +++ b/test/Helper/TestAsset/PartialLoopToArrayImplementor.php @@ -4,7 +4,7 @@ namespace LaminasTest\View\Helper\TestAsset; -class ToArrayTest +class PartialLoopToArrayImplementor { private array $data; diff --git a/test/HelperPluginManagerCompatibilityTest.php b/test/HelperPluginManagerCompatibilityTest.php index 840f05930..41917aefa 100644 --- a/test/HelperPluginManagerCompatibilityTest.php +++ b/test/HelperPluginManagerCompatibilityTest.php @@ -52,13 +52,15 @@ protected function getV2InvalidPluginException(): string /** * @psalm-return Generator */ - public function aliasProvider(): Generator + public static function aliasProvider(): Generator { - $pluginManager = $this->getPluginManager(); + $pluginManager = self::getPluginManager(); $r = new ReflectionProperty($pluginManager, 'aliases'); $aliases = $r->getValue($pluginManager); + self::assertIsArray($aliases); foreach ($aliases as $alias => $target) { + self::assertIsString($target); // Skipping conditionally since it depends on laminas-mvc if (! class_exists(ControllerPluginManager::class) && strpos($target, '\\Url')) { continue; diff --git a/test/HelperPluginManagerTest.php b/test/HelperPluginManagerTest.php index cad1ada77..1bd19e922 100644 --- a/test/HelperPluginManagerTest.php +++ b/test/HelperPluginManagerTest.php @@ -9,8 +9,8 @@ use Laminas\Mvc\I18n\Translator as MvcTranslator; use Laminas\ServiceManager\Config; use Laminas\ServiceManager\Exception\InvalidServiceException; +use Laminas\ServiceManager\Exception\ServiceNotFoundException; use Laminas\ServiceManager\ServiceManager; -use Laminas\View\Exception\InvalidHelperException; use Laminas\View\Helper\Doctype; use Laminas\View\Helper\HeadTitle; use Laminas\View\Helper\HelperInterface; @@ -20,8 +20,6 @@ use Laminas\View\Renderer\PhpRenderer; use PHPUnit\Framework\TestCase; -use function method_exists; - class HelperPluginManagerTest extends TestCase { private HelperPluginManager $helpers; @@ -57,25 +55,21 @@ public function testNoRendererInjectedInHelperWhenRendererIsNotPresent(): void $this->assertNull($helper->getView()); } - public function testRegisteringInvalidHelperRaisesException(): void + public function testRegisteringInvalidHelperRaisesInvalidServiceException(): void { $helpers = new HelperPluginManager(new ServiceManager(), [ 'factories' => [ 'test' => fn() => $this, ], ]); - $this->expectException($this->getServiceNotFoundException($helpers)); + $this->expectException(InvalidServiceException::class); $helpers->get('test'); } - public function testLoadingInvalidHelperRaisesException(): void + public function testRequestingAnUnregisteredHelperRaisesServiceNotFoundException(): void { - $helpers = new HelperPluginManager(new ServiceManager(), [ - 'invokables' => [ - 'test' => static::class, - ], - ]); - $this->expectException($this->getServiceNotFoundException($helpers)); + $helpers = new HelperPluginManager(new ServiceManager(), []); + $this->expectException(ServiceNotFoundException::class); $helpers->get('test'); } @@ -196,15 +190,4 @@ public function testDoctypeFactoryExists(): void { self::assertTrue($this->helpers->has(Doctype::class)); } - - /** - * @psalm-return InvalidHelperException::class|InvalidServiceException::class - */ - private function getServiceNotFoundException(HelperPluginManager $manager): string - { - if (method_exists($manager, 'configure')) { - return InvalidServiceException::class; - } - return InvalidHelperException::class; - } } diff --git a/test/Model/ViewModelTest.php b/test/Model/ViewModelTest.php index a2a66922f..fba20da43 100644 --- a/test/Model/ViewModelTest.php +++ b/test/Model/ViewModelTest.php @@ -11,6 +11,7 @@ use Laminas\View\Model\ViewModel; use Laminas\View\Variables as ViewVariables; use LaminasTest\View\Model\TestAsset\Variable; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use stdClass; @@ -369,7 +370,7 @@ public function testCloneWithArray(): void * 2: null|string, * }> */ - public function variableValue(): array + public static function variableValue(): array { return [ // variables default expected @@ -392,26 +393,21 @@ public function variableValue(): array ]; } - /** - * @dataProvider variableValue - * @param array|ArrayObject $variables - * @param string|null $default - * @param string|null $expected - */ - public function testGetVariableSetByConstruct($variables, $default, $expected): void - { + /** @param array|ArrayObject $variables */ + #[DataProvider('variableValue')] + public function testGetVariableSetByConstruct( + iterable $variables, + string|null $default, + string|null $expected + ): void { $model = new ViewModel($variables); self::assertSame($expected, $model->getVariable('foo', $default)); } - /** - * @dataProvider variableValue - * @param array|ArrayObject $variables - * @param string|null $default - * @param string|null $expected - */ - public function testGetVariableSetBySetter($variables, $default, $expected): void + /** @param array|ArrayObject $variables */ + #[DataProvider('variableValue')] + public function testGetVariableSetBySetter(iterable $variables, string|null $default, string|null $expected): void { $model = new ViewModel(); $model->setVariables($variables); diff --git a/test/PhpRendererTest.php b/test/PhpRendererTest.php index 9f0fde52c..7be4b4875 100644 --- a/test/PhpRendererTest.php +++ b/test/PhpRendererTest.php @@ -5,7 +5,6 @@ namespace LaminasTest\View; use ArrayObject; -use Exception; use Laminas\Filter\FilterChain; use Laminas\ServiceManager\ServiceManager; use Laminas\View\Exception\DomainException; @@ -23,6 +22,7 @@ use LaminasTest\View\TestAsset\Invokable; use LaminasTest\View\TestAsset\SharedInstance; use LaminasTest\View\TestAsset\Uninvokable; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use ReflectionObject; use stdClass; @@ -31,8 +31,11 @@ use function assert; use function realpath; use function restore_error_handler; +use function set_error_handler; use function str_replace; +use const E_WARNING; + class PhpRendererTest extends TestCase { private PhpRenderer $renderer; @@ -126,7 +129,7 @@ public function testPassingValidStringClassToSetHelperPluginManagerCreatesIt(): /** * @psalm-return array */ - public function invalidPluginManagers(): array + public static function invalidPluginManagers(): array { return [ [true], @@ -137,11 +140,8 @@ public function invalidPluginManagers(): array ]; } - /** - * @dataProvider invalidPluginManagers - * @param mixed $plugins - */ - public function testPassingInvalidArgumentToSetHelperPluginManagerRaisesException($plugins): void + #[DataProvider('invalidPluginManagers')] + public function testPassingInvalidArgumentToSetHelperPluginManagerRaisesException(mixed $plugins): void { $this->expectException(ExceptionInterface::class); $this->expectExceptionMessage('must extend'); @@ -332,19 +332,16 @@ public function testRenderedViewModelIsRegisteredAsCurrentViewModel(): void public function testRendererRaisesExceptionInCaseOfExceptionInView(): void { $resolver = new TemplateMapResolver([ - 'exception' => __DIR__ . '../../Mvc/View/_files/exception.phtml', + 'exception' => __DIR__ . '/_templates/exception.phtml', ]); $this->renderer->setResolver($resolver); $model = new ViewModel(); $model->setTemplate('exception'); - try { - $this->renderer->render($model); - $this->fail('Exception from renderer should propagate'); - } catch (Throwable $e) { - $this->assertInstanceOf(Exception::class, $e); - } + $this->expectException(DomainException::class); + $this->expectExceptionMessage('I was thrown in the view'); + $this->renderer->render($model); } public function testRendererRaisesExceptionIfResolverCannotResolveTemplate(): void @@ -359,7 +356,7 @@ public function testRendererRaisesExceptionIfResolverCannotResolveTemplate(): vo * @return string[][] * @psalm-return array{0: array{0: '/does/not/exists'}, 1: array{0: '.'}} */ - public function invalidTemplateFiles(): array + public static function invalidTemplateFiles(): array { return [ ['/does/not/exists'], @@ -367,9 +364,7 @@ public function invalidTemplateFiles(): array ]; } - /** - * @dataProvider invalidTemplateFiles - */ + #[DataProvider('invalidTemplateFiles')] public function testRendererRaisesExceptionIfResolvedTemplateIsInvalid(string $template): void { $resolver = new TemplateMapResolver([ diff --git a/test/Renderer/JsonRendererTest.php b/test/Renderer/JsonRendererTest.php index db55521d8..d360e5ab1 100644 --- a/test/Renderer/JsonRendererTest.php +++ b/test/Renderer/JsonRendererTest.php @@ -9,6 +9,7 @@ use Laminas\View\Model\JsonModel; use Laminas\View\Model\ViewModel; use Laminas\View\Renderer\JsonRenderer; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use stdClass; @@ -101,7 +102,7 @@ public function testCanMergeChildModelsWithoutCaptureToValues(): void /** * @psalm-return array */ - public function getNonObjectModels(): array + public static function getNonObjectModels(): array { return [ ['string'], @@ -112,11 +113,8 @@ public function getNonObjectModels(): array ]; } - /** - * @dataProvider getNonObjectModels - * @param mixed $model - */ - public function testRendersNonObjectModelAsJson($model): void + #[DataProvider('getNonObjectModels')] + public function testRendersNonObjectModelAsJson(mixed $model): void { $expected = json_encode($model, JSON_THROW_ON_ERROR); /** @psalm-suppress MixedArgument $test */ @@ -183,11 +181,8 @@ public function testRendersViewModelsWithoutChildrenWithJsonpCallback(): void $this->assertEquals($expected, $test); } - /** - * @dataProvider getNonObjectModels - * @param mixed $model - */ - public function testRendersNonObjectModelAsJsonWithJsonpCallback($model): void + #[DataProvider('getNonObjectModels')] + public function testRendersNonObjectModelAsJsonWithJsonpCallback(mixed $model): void { $expected = 'callback(' . json_encode($model, JSON_THROW_ON_ERROR) . ');'; $this->renderer->setJsonpCallback('callback'); diff --git a/test/Resolver/PrefixPathStackResolverTest.php b/test/Resolver/PrefixPathStackResolverTest.php index ad6fbfda3..2ceff477a 100644 --- a/test/Resolver/PrefixPathStackResolverTest.php +++ b/test/Resolver/PrefixPathStackResolverTest.php @@ -5,16 +5,13 @@ namespace LaminasTest\View\Resolver; use Laminas\View\Resolver\PrefixPathStackResolver; -use Laminas\View\Resolver\ResolverInterface; +use Laminas\View\Resolver\TemplateMapResolver; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use function realpath; -/** - * Tests for {@see \Laminas\View\Resolver\PrefixPathStackResolver} - * - * @covers \Laminas\View\Resolver\PrefixPathStackResolver - */ +#[CoversClass(PrefixPathStackResolver::class)] class PrefixPathStackResolverTest extends TestCase { private string $basePath; @@ -63,21 +60,11 @@ public function testResolveWithCongruentPrefix(): void public function testSetCustomPathStackResolver(): void { - $mockResolver = $this->createMock(ResolverInterface::class); - $mockResolver->expects(self::exactly(3)) - ->method('resolve') - ->withConsecutive( - ['/bar', null], - ['/baz', null], - ['/tab', null] - )->willReturnOnConsecutiveCalls( - '1111', - '2222', - false - ); - $resolver = new PrefixPathStackResolver([ - 'foo' => $mockResolver, + 'foo' => new TemplateMapResolver([ + '/bar' => '1111', + '/baz' => '2222', + ]), ]); $this->assertSame('1111', $resolver->resolve('foo/bar')); diff --git a/test/Resolver/RelativeFallbackResolverTest.php b/test/Resolver/RelativeFallbackResolverTest.php index 22ecabcc4..6fd8e15f7 100644 --- a/test/Resolver/RelativeFallbackResolverTest.php +++ b/test/Resolver/RelativeFallbackResolverTest.php @@ -12,14 +12,13 @@ use Laminas\View\Resolver\ResolverInterface; use Laminas\View\Resolver\TemplateMapResolver; use Laminas\View\Resolver\TemplatePathStack; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use stdClass; use function realpath; -/** - * @covers \Laminas\View\Resolver\RelativeFallbackResolver - */ +#[CoversClass(RelativeFallbackResolver::class)] class RelativeFallbackResolverTest extends TestCase { public function testReturnsResourceFromTheSameNameSpaceWithMapResolver(): void diff --git a/test/Resolver/TemplatePathStackTest.php b/test/Resolver/TemplatePathStackTest.php index cbeaec3b8..9d2a407ae 100644 --- a/test/Resolver/TemplatePathStackTest.php +++ b/test/Resolver/TemplatePathStackTest.php @@ -7,6 +7,7 @@ use ArrayObject; use Laminas\View\Exception; use Laminas\View\Resolver\TemplatePathStack; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use stdClass; @@ -143,7 +144,7 @@ public function testReturnsFullPathNameWhenAbleToResolveScriptPath(): void /** * @psalm-return array */ - public function invalidOptions(): array + public static function invalidOptions(): array { return [ [true], @@ -154,11 +155,8 @@ public function invalidOptions(): array ]; } - /** - * @param mixed $options - * @dataProvider invalidOptions - */ - public function testSettingOptionsWithInvalidArgumentRaisesException($options): void + #[DataProvider('invalidOptions')] + public function testSettingOptionsWithInvalidArgumentRaisesException(mixed $options): void { $this->expectException(Exception\ExceptionInterface::class); /** @psalm-suppress MixedArgument */ @@ -168,7 +166,7 @@ public function testSettingOptionsWithInvalidArgumentRaisesException($options): /** * @return array|ArrayObject}> */ - public function validOptions(): array + public static function validOptions(): array { $options = [ 'lfi_protection' => false, @@ -182,8 +180,8 @@ public function validOptions(): array /** * @param array|ArrayObject $options - * @dataProvider validOptions */ + #[DataProvider('validOptions')] public function testAllowsSettingOptions($options): void { $options['script_paths'] = $this->paths; @@ -197,8 +195,8 @@ public function testAllowsSettingOptions($options): void /** * @param array|ArrayObject $options - * @dataProvider validOptions */ + #[DataProvider('validOptions')] public function testAllowsPassingOptionsToConstructor($options): void { $options['script_paths'] = $this->paths; diff --git a/test/Strategy/JsonStrategyTest.php b/test/Strategy/JsonStrategyTest.php index 214dbfbfd..0daa7efb3 100644 --- a/test/Strategy/JsonStrategyTest.php +++ b/test/Strategy/JsonStrategyTest.php @@ -14,6 +14,7 @@ use Laminas\View\Renderer\JsonRenderer; use Laminas\View\Strategy\JsonStrategy; use Laminas\View\ViewEvent; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use function iterator_to_array; @@ -308,7 +309,7 @@ public function testCharsetIsMutable(): void * @return string[][] * @psalm-return array{utf-16: array{0: 'utf-16'}, utf-32: array{0: 'utf-32'}} */ - public function multibyteCharsets(): array + public static function multibyteCharsets(): array { return [ 'utf-16' => ['utf-16'], @@ -316,11 +317,8 @@ public function multibyteCharsets(): array ]; } - /** - * @dataProvider multibyteCharsets - * @param string $charset - */ - public function testContentTransferEncodingHeaderSetToBinaryForSpecificMultibyteCharsets($charset): void + #[DataProvider('multibyteCharsets')] + public function testContentTransferEncodingHeaderSetToBinaryForSpecificMultibyteCharsets(string $charset): void { $this->strategy->setCharset($charset); diff --git a/test/_templates/exception.phtml b/test/_templates/exception.phtml new file mode 100644 index 000000000..ce368bb24 --- /dev/null +++ b/test/_templates/exception.phtml @@ -0,0 +1,3 @@ +