diff --git a/.github/workflows/checkout.yml b/.github/workflows/checkout.yml index d79cb2e1..f9787deb 100644 --- a/.github/workflows/checkout.yml +++ b/.github/workflows/checkout.yml @@ -2,7 +2,7 @@ name: Pckg Framework CI on: push: - branches: [ master ] + branches: [ master, master-yoda ] pull_request: branches: [ master ] @@ -25,10 +25,10 @@ jobs: uses: actions/cache@v2 with: path: vendor - key: composer-${{ hashFiles('composer.lock') }} + key: composer-v1-${{ hashFiles('composer.lock') }} - name: Install Composer dependencies - run: composer install --dev --prefer-dist --no-progress --no-suggest --optimize-autoloader --ignore-platform-reqs + run: composer install --prefer-dist --no-progress --optimize-autoloader --ignore-platform-reqs - name: Copy Codeception config run: cp codeception.sample.travis.yml codeception.yml diff --git a/.gitignore b/.gitignore index a5ee1d21..3648d3ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .idea/ vendor/ -tests/_data/* tests/_output/* -codeception.yml \ No newline at end of file +codeception.yml diff --git a/composer.json b/composer.json index af1cfbaa..2fd74051 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ "filp/whoops": "2.*", "tgalopin/html-sanitizer": "dev-master", "ezyang/htmlpurifier": "dev-master", - "ext-json": "*" + "ext-json": "*", + "ext-pcntl": "*" }, "require-dev": { "maximebf/debugbar": "1.*", @@ -41,6 +42,7 @@ "Pckg": "src\\" }, "files": [ + "src/Pckg/Framework/Helper/functions_bc.php", "src/Pckg/Framework/Helper/functions.php" ] }, @@ -49,14 +51,14 @@ "true || vendor/bin/phpunit --help --stop-on-defect", "true || vendor/bin/phpcloc cloc src/", "vendor/bin/phpstan analyse src/ --level=1", - "vendor/bin/phpcs --extensions=php --warning-severity=8 --error-severity=1 --standard=PSR12 --parallel=2 -p src/", + "vendor/bin/phpcs -s --standard=ruleset.xml --extensions=php --warning-severity=8 --error-severity=1 --parallel=2 -p src/", "vendor/bin/codecept run" ], "applycsandpatch": [ "composer autofix && composer autopatch" ], "autofix": [ - "vendor/bin/phpcs --extensions=php --report-diff=phpcs.diff --warning-severity=8 --error-severity=1 --standard=PSR12 --parallel=2 -p src/" + "vendor/bin/phpcs --standard=ruleset.xml --extensions=php --report-diff=phpcs.diff --warning-severity=8 --error-severity=1 --parallel=2 -p src/" ], "autopatch": [ "patch -p0 -ui phpcs.diff ; rm phpcs.diff" diff --git a/composer.lock b/composer.lock index 0c0302b1..e841112a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,44 +4,43 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9dbe0d747d42c44ba24189ebb6bc0084", + "content-hash": "0861a9685c5c575c260ae9b1cac6c2f0", "packages": [ { "name": "doctrine/cache", - "version": "1.10.2", + "version": "1.11.3", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "13e3381b25847283a91948d04640543941309727" + "reference": "3bb5588cec00a0268829cc4a518490df6741af9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/13e3381b25847283a91948d04640543941309727", - "reference": "13e3381b25847283a91948d04640543941309727", + "url": "https://api.github.com/repos/doctrine/cache/zipball/3bb5588cec00a0268829cc4a518490df6741af9d", + "reference": "3bb5588cec00a0268829cc4a518490df6741af9d", "shasum": "" }, "require": { "php": "~7.1 || ^8.0" }, "conflict": { - "doctrine/common": ">2.2,<2.4" + "doctrine/common": ">2.2,<2.4", + "psr/cache": ">=3" }, "require-dev": { "alcaeus/mongo-php-adapter": "^1.1", - "doctrine/coding-standard": "^6.0", + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^8.0", "mongodb/mongodb": "^1.1", - "phpunit/phpunit": "^7.0", - "predis/predis": "~1.0" + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "predis/predis": "~1.0", + "psr/cache": "^1.0 || ^2.0", + "symfony/cache": "^4.4 || ^5.2" }, "suggest": { "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" @@ -88,7 +87,7 @@ ], "support": { "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/1.10.x" + "source": "https://github.com/doctrine/cache/tree/1.11.3" }, "funding": [ { @@ -104,7 +103,7 @@ "type": "tidelift" } ], - "time": "2020-07-07T18:54:01+00:00" + "time": "2021-05-25T09:01:55+00:00" }, { "name": "ezyang/htmlpurifier", @@ -112,12 +111,12 @@ "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "214cb8a6934f9682ce5a9d7a7f5a76801c7822e6" + "reference": "3a368d76686683d73c3463c7d051c12664f54ad2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/214cb8a6934f9682ce5a9d7a7f5a76801c7822e6", - "reference": "214cb8a6934f9682ce5a9d7a7f5a76801c7822e6", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/3a368d76686683d73c3463c7d051c12664f54ad2", + "reference": "3a368d76686683d73c3463c7d051c12664f54ad2", "shasum": "" }, "require": { @@ -159,20 +158,20 @@ "issues": "https://github.com/ezyang/htmlpurifier/issues", "source": "https://github.com/ezyang/htmlpurifier/tree/master" }, - "time": "2021-01-26T16:11:50+00:00" + "time": "2021-05-22T00:46:13+00:00" }, { "name": "filp/whoops", - "version": "2.9.2", + "version": "2.12.1", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "df7933820090489623ce0be5e85c7e693638e536" + "reference": "c13c0be93cff50f88bbd70827d993026821914dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/df7933820090489623ce0be5e85c7e693638e536", - "reference": "df7933820090489623ce0be5e85c7e693638e536", + "url": "https://api.github.com/repos/filp/whoops/zipball/c13c0be93cff50f88bbd70827d993026821914dd", + "reference": "c13c0be93cff50f88bbd70827d993026821914dd", "shasum": "" }, "require": { @@ -222,7 +221,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.9.2" + "source": "https://github.com/filp/whoops/tree/2.12.1" }, "funding": [ { @@ -230,62 +229,7 @@ "type": "github" } ], - "time": "2021-01-24T12:00:00+00:00" - }, - { - "name": "fzaninotto/faker", - "version": "v1.9.2", - "source": { - "type": "git", - "url": "https://github.com/fzaninotto/Faker.git", - "reference": "848d8125239d7dbf8ab25cb7f054f1a630e68c2e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/848d8125239d7dbf8ab25cb7f054f1a630e68c2e", - "reference": "848d8125239d7dbf8ab25cb7f054f1a630e68c2e", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "ext-intl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7", - "squizlabs/php_codesniffer": "^2.9.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "psr-4": { - "Faker\\": "src/Faker/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "François Zaninotto" - } - ], - "description": "Faker is a PHP library that generates fake data for you.", - "keywords": [ - "data", - "faker", - "fixtures" - ], - "support": { - "issues": "https://github.com/fzaninotto/Faker/issues", - "source": "https://github.com/fzaninotto/Faker/tree/v1.9.2" - }, - "abandoned": true, - "time": "2020-12-11T09:56:16+00:00" + "time": "2021-04-25T12:00:00+00:00" }, { "name": "josegonzalez/dotenv", @@ -647,12 +591,12 @@ "source": { "type": "git", "url": "https://github.com/pckg/cache.git", - "reference": "4974920700ffabd428723b7bd0810e5b9418697a" + "reference": "7b56641cbacf9deb724e337335ccfe38c72c06bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/cache/zipball/4974920700ffabd428723b7bd0810e5b9418697a", - "reference": "4974920700ffabd428723b7bd0810e5b9418697a", + "url": "https://api.github.com/repos/pckg/cache/zipball/7b56641cbacf9deb724e337335ccfe38c72c06bf", + "reference": "7b56641cbacf9deb724e337335ccfe38c72c06bf", "shasum": "" }, "require": { @@ -685,7 +629,7 @@ "issues": "https://github.com/pckg/cache/issues", "source": "https://github.com/pckg/cache/tree/master" }, - "time": "2021-02-05T20:19:06+00:00" + "time": "2021-03-05T18:25:17+00:00" }, { "name": "pckg/collection", @@ -693,12 +637,12 @@ "source": { "type": "git", "url": "https://github.com/pckg/collection.git", - "reference": "f363854132cfd29b62490e0f794d18e4cbf43a0c" + "reference": "381871e595a2cb32acdfc5718ffb9f408f3be39a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/collection/zipball/f363854132cfd29b62490e0f794d18e4cbf43a0c", - "reference": "f363854132cfd29b62490e0f794d18e4cbf43a0c", + "url": "https://api.github.com/repos/pckg/collection/zipball/381871e595a2cb32acdfc5718ffb9f408f3be39a", + "reference": "381871e595a2cb32acdfc5718ffb9f408f3be39a", "shasum": "" }, "require": { @@ -735,7 +679,7 @@ "issues": "https://github.com/pckg/collection/issues", "source": "https://github.com/pckg/collection/tree/master" }, - "time": "2021-02-05T21:19:20+00:00" + "time": "2021-05-20T13:45:06+00:00" }, { "name": "pckg/concept", @@ -743,17 +687,19 @@ "source": { "type": "git", "url": "https://github.com/pckg/concept.git", - "reference": "893fc26339bf78a32e5c8c46a1e37bf28d874392" + "reference": "ad33e34461069df7d0f2084282ca95815b5d6170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/concept/zipball/893fc26339bf78a32e5c8c46a1e37bf28d874392", - "reference": "893fc26339bf78a32e5c8c46a1e37bf28d874392", + "url": "https://api.github.com/repos/pckg/concept/zipball/ad33e34461069df7d0f2084282ca95815b5d6170", + "reference": "ad33e34461069df7d0f2084282ca95815b5d6170", "shasum": "" }, "require-dev": { "pckg-app/frontend-dev": "dev-master", - "pckg/framework": "dev-master" + "pckg/framework": "dev-master-yoda", + "pckg/htmlbuilder": "dev-master", + "pckg/manager": "dev-master" }, "default-branch": true, "type": "library", @@ -762,7 +708,8 @@ "Pckg": "src\\" }, "files": [ - "src/Pckg/Concept/Helper/functions.php" + "src/Pckg/Concept/Helper/functions.php", + "src/Pckg/Concept/Helper/functions_bc.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -781,7 +728,7 @@ "issues": "https://github.com/pckg/concept/issues", "source": "https://github.com/pckg/concept/tree/master" }, - "time": "2021-02-05T19:04:20+00:00" + "time": "2021-05-25T12:23:46+00:00" }, { "name": "pckg/database", @@ -789,12 +736,12 @@ "source": { "type": "git", "url": "https://github.com/pckg/database.git", - "reference": "93f65eefcb9de0d06b7e48203d2574f38b98f28a" + "reference": "1d3329268bd04836b9d906faa2eb0f66b10be839" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/database/zipball/93f65eefcb9de0d06b7e48203d2574f38b98f28a", - "reference": "93f65eefcb9de0d06b7e48203d2574f38b98f28a", + "url": "https://api.github.com/repos/pckg/database/zipball/1d3329268bd04836b9d906faa2eb0f66b10be839", + "reference": "1d3329268bd04836b9d906faa2eb0f66b10be839", "shasum": "" }, "require": { @@ -841,7 +788,7 @@ "issues": "https://github.com/pckg/database/issues", "source": "https://github.com/pckg/database/tree/master" }, - "time": "2021-02-11T15:30:24+00:00" + "time": "2021-05-20T19:02:39+00:00" }, { "name": "pckg/locale", @@ -849,12 +796,12 @@ "source": { "type": "git", "url": "https://github.com/pckg/locale.git", - "reference": "6e13abf62f6d4dc1557427154859c76e4c5c73e6" + "reference": "5ad051c578910670d8619d04adeadaf440facff6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/locale/zipball/6e13abf62f6d4dc1557427154859c76e4c5c73e6", - "reference": "6e13abf62f6d4dc1557427154859c76e4c5c73e6", + "url": "https://api.github.com/repos/pckg/locale/zipball/5ad051c578910670d8619d04adeadaf440facff6", + "reference": "5ad051c578910670d8619d04adeadaf440facff6", "shasum": "" }, "require-dev": { @@ -886,20 +833,20 @@ "issues": "https://github.com/pckg/locale/issues", "source": "https://github.com/pckg/locale/tree/master" }, - "time": "2021-02-06T11:47:33+00:00" + "time": "2021-03-05T18:27:18+00:00" }, { "name": "psr/log", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { @@ -923,7 +870,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", @@ -934,9 +881,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.3" + "source": "https://github.com/php-fig/log/tree/1.1.4" }, - "time": "2020-03-23T09:12:05+00:00" + "time": "2021-05-03T11:20:27+00:00" }, { "name": "rollbar/rollbar", @@ -1004,7 +951,7 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.22.0", + "version": "v1.22.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -1063,7 +1010,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" }, "funding": [ { @@ -1132,16 +1079,16 @@ }, { "name": "twig/twig", - "version": "v1.44.2", + "version": "v1.44.4", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "138c493c5b8ee7cff3821f80b8896d371366b5fe" + "reference": "4d400421528e9fa40caaffcf7824c172526dd99d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/138c493c5b8ee7cff3821f80b8896d371366b5fe", - "reference": "138c493c5b8ee7cff3821f80b8896d371366b5fe", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/4d400421528e9fa40caaffcf7824c172526dd99d", + "reference": "4d400421528e9fa40caaffcf7824c172526dd99d", "shasum": "" }, "require": { @@ -1194,7 +1141,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v1.44.2" + "source": "https://github.com/twigphp/Twig/tree/v1.44.4" }, "funding": [ { @@ -1206,35 +1153,31 @@ "type": "tidelift" } ], - "time": "2021-01-05T10:10:05+00:00" + "time": "2021-05-16T12:11:20+00:00" } ], "packages-dev": [ { - "name": "appzcoder/phpcloc", - "version": "v0.0.2", + "name": "assetic/framework", + "version": "v1.0.5", "source": { "type": "git", - "url": "https://github.com/appzcoder/phpcloc.git", - "reference": "b8da7420a826361e66959e024e8223a76b5139eb" + "url": "https://github.com/assetic-php/assetic.git", + "reference": "8ab3638325af9cd144242765494a9dc9b53ab430" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appzcoder/phpcloc/zipball/b8da7420a826361e66959e024e8223a76b5139eb", - "reference": "b8da7420a826361e66959e024e8223a76b5139eb", + "url": "https://api.github.com/repos/assetic-php/assetic/zipball/8ab3638325af9cd144242765494a9dc9b53ab430", + "reference": "8ab3638325af9cd144242765494a9dc9b53ab430", "shasum": "" }, "require": { - "php": ">=5.5.9", - "symfony/console": "^3.4 || ^4.0" + "php": ">=5.3.1" }, - "bin": [ - "phpcloc" - ], "type": "library", "autoload": { - "psr-4": { - "Appzcoder\\PHPCloc\\": "src/" + "psr-0": { + "Assetic": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1243,22 +1186,22 @@ ], "authors": [ { - "name": "Sohel Amin", - "email": "sohelamincse@gmail.com" + "name": "Kris Wallsmith", + "email": "kris.wallsmith@gmail.com", + "homepage": "http://kriswallsmith.net/" } ], - "description": "Cloc & duplicate code checker tool.", + "description": "Asset Management for PHP", + "homepage": "https://github.com/kriswallsmith/assetic", "keywords": [ - "cloc", - "count lines of code", - "duplicate code checker", - "phpcloc" + "assets", + "compression", + "minification" ], "support": { - "issues": "https://github.com/appzcoder/phpcloc/issues", - "source": "https://github.com/appzcoder/phpcloc/tree/master" + "source": "https://github.com/assetic-php/assetic/tree/v1.0.5" }, - "time": "2018-05-27T06:27:35+00:00" + "time": "2014-12-12T05:07:58+00:00" }, { "name": "behat/gherkin", @@ -1382,16 +1325,16 @@ }, { "name": "codeception/codeception", - "version": "4.1.17", + "version": "4.1.20", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "c153b1ab289b3e3109e685379aa8847c54ac2b68" + "reference": "d8b16e13e1781dbc3a7ae8292117d520c89a9c5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/c153b1ab289b3e3109e685379aa8847c54ac2b68", - "reference": "c153b1ab289b3e3109e685379aa8847c54ac2b68", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/d8b16e13e1781dbc3a7ae8292117d520c89a9c5a", + "reference": "d8b16e13e1781dbc3a7ae8292117d520c89a9c5a", "shasum": "" }, "require": { @@ -1465,7 +1408,7 @@ ], "support": { "issues": "https://github.com/Codeception/Codeception/issues", - "source": "https://github.com/Codeception/Codeception/tree/4.1.17" + "source": "https://github.com/Codeception/Codeception/tree/4.1.20" }, "funding": [ { @@ -1473,7 +1416,7 @@ "type": "open_collective" } ], - "time": "2021-02-01T07:30:47+00:00" + "time": "2021-04-02T16:41:51+00:00" }, { "name": "codeception/lib-asserts", @@ -1531,16 +1474,16 @@ }, { "name": "codeception/lib-innerbrowser", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/Codeception/lib-innerbrowser.git", - "reference": "b7406c710684c255d9b067d7795269a5585a0406" + "reference": "4b0d89b37fe454e060a610a85280a87ab4f534f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/b7406c710684c255d9b067d7795269a5585a0406", - "reference": "b7406c710684c255d9b067d7795269a5585a0406", + "url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/4b0d89b37fe454e060a610a85280a87ab4f534f1", + "reference": "4b0d89b37fe454e060a610a85280a87ab4f534f1", "shasum": "" }, "require": { @@ -1585,9 +1528,9 @@ ], "support": { "issues": "https://github.com/Codeception/lib-innerbrowser/issues", - "source": "https://github.com/Codeception/lib-innerbrowser/tree/1.4.0" + "source": "https://github.com/Codeception/lib-innerbrowser/tree/1.5.0" }, - "time": "2021-01-29T18:17:25+00:00" + "time": "2021-04-23T06:18:29+00:00" }, { "name": "codeception/module-asserts", @@ -1646,6 +1589,58 @@ }, "time": "2020-10-21T16:48:15+00:00" }, + { + "name": "codeception/module-db", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-db.git", + "reference": "8c8076cd05d4db95798acd7dba2a56578210982c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-db/zipball/8c8076cd05d4db95798acd7dba2a56578210982c", + "reference": "8c8076cd05d4db95798acd7dba2a56578210982c", + "shasum": "" + }, + "require": { + "codeception/codeception": "*@dev", + "php": ">=5.6.0 <9.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + } + ], + "description": "DB module for Codeception", + "homepage": "http://codeception.com/", + "keywords": [ + "codeception", + "database-testing", + "db-testing" + ], + "support": { + "issues": "https://github.com/Codeception/module-db/issues", + "source": "https://github.com/Codeception/module-db/tree/1.1.0" + }, + "time": "2020-12-20T13:37:07+00:00" + }, { "name": "codeception/module-phpbrowser", "version": "1.0.2", @@ -1706,18 +1701,67 @@ }, "time": "2020-10-24T15:29:28+00:00" }, + { + "name": "codeception/module-redis", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-redis.git", + "reference": "83c6db34349f1bd8dbfe4b778d7645c9ffcacfb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-redis/zipball/83c6db34349f1bd8dbfe4b778d7645c9ffcacfb7", + "reference": "83c6db34349f1bd8dbfe4b778d7645c9ffcacfb7", + "shasum": "" + }, + "require": { + "codeception/codeception": "^4.0", + "php": ">=5.6.0 <9.0", + "predis/predis": "^1.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Dmitriy Maltsev" + } + ], + "description": "Redis module for Codeception", + "homepage": "http://codeception.com/", + "keywords": [ + "codeception", + "redis" + ], + "support": { + "issues": "https://github.com/Codeception/module-redis/issues", + "source": "https://github.com/Codeception/module-redis/tree/1.1.0" + }, + "time": "2021-03-31T16:02:02+00:00" + }, { "name": "codeception/module-rest", - "version": "1.2.7", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/Codeception/module-rest.git", - "reference": "beeb5a91a97d042273bf10f00063e9b8f541879a" + "reference": "293a0103d5257b7c884ef276147a9a06914e878f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/module-rest/zipball/beeb5a91a97d042273bf10f00063e9b8f541879a", - "reference": "beeb5a91a97d042273bf10f00063e9b8f541879a", + "url": "https://api.github.com/repos/Codeception/module-rest/zipball/293a0103d5257b7c884ef276147a9a06914e878f", + "reference": "293a0103d5257b7c884ef276147a9a06914e878f", "shasum": "" }, "require": { @@ -1756,22 +1800,22 @@ ], "support": { "issues": "https://github.com/Codeception/module-rest/issues", - "source": "https://github.com/Codeception/module-rest/tree/1.2.7" + "source": "https://github.com/Codeception/module-rest/tree/1.3.1" }, - "time": "2020-11-04T16:58:11+00:00" + "time": "2021-04-23T08:12:24+00:00" }, { "name": "codeception/module-webdriver", - "version": "dev-master", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/Codeception/module-webdriver.git", - "reference": "63ea08880a44df809bdfbca08597e1b68cee9f87" + "reference": "ebbe729c630415e8caf6b0087e457906f0c6c0c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/module-webdriver/zipball/63ea08880a44df809bdfbca08597e1b68cee9f87", - "reference": "63ea08880a44df809bdfbca08597e1b68cee9f87", + "url": "https://api.github.com/repos/Codeception/module-webdriver/zipball/ebbe729c630415e8caf6b0087e457906f0c6c0c6", + "reference": "ebbe729c630415e8caf6b0087e457906f0c6c0c6", "shasum": "" }, "require": { @@ -1782,7 +1826,6 @@ "suggest": { "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests" }, - "default-branch": true, "type": "library", "autoload": { "classmap": [ @@ -1813,9 +1856,9 @@ ], "support": { "issues": "https://github.com/Codeception/module-webdriver/issues", - "source": "https://github.com/Codeception/module-webdriver/tree/1.2.0" + "source": "https://github.com/Codeception/module-webdriver/tree/1.2.1" }, - "time": "2021-01-17T19:23:20+00:00" + "time": "2021-04-23T17:30:57+00:00" }, { "name": "codeception/phpunit-wrapper", @@ -1866,6 +1909,52 @@ }, "time": "2020-12-28T13:59:47+00:00" }, + { + "name": "codeception/specify", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Specify.git", + "reference": "17ae6d4d6cb201ef5461f6587ecfcff8c177f854" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Specify/zipball/17ae6d4d6cb201ef5461f6587ecfcff8c177f854", + "reference": "17ae6d4d6cb201ef5461f6587ecfcff8c177f854", + "shasum": "" + }, + "require": { + "myclabs/deep-copy": "~1.1", + "php": ">=7.1.0", + "phpunit/phpunit": ">=7.0 <10.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Codeception\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@codeception.com" + }, + { + "name": "Gustavo Nieves", + "homepage": "https://medium.com/@ganieves" + } + ], + "description": "BDD code blocks for PHPUnit and Codeception", + "support": { + "issues": "https://github.com/Codeception/Specify/issues", + "source": "https://github.com/Codeception/Specify/tree/1.4.0" + }, + "time": "2020-08-27T20:17:29+00:00" + }, { "name": "codeception/stub", "version": "3.7.0", @@ -1902,26 +1991,25 @@ }, { "name": "defuse/php-encryption", - "version": "v2.2.1", + "version": "v2.3.1", "source": { "type": "git", "url": "https://github.com/defuse/php-encryption.git", - "reference": "0f407c43b953d571421e0020ba92082ed5fb7620" + "reference": "77880488b9954b7884c25555c2a0ea9e7053f9d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/defuse/php-encryption/zipball/0f407c43b953d571421e0020ba92082ed5fb7620", - "reference": "0f407c43b953d571421e0020ba92082ed5fb7620", + "url": "https://api.github.com/repos/defuse/php-encryption/zipball/77880488b9954b7884c25555c2a0ea9e7053f9d2", + "reference": "77880488b9954b7884c25555c2a0ea9e7053f9d2", "shasum": "" }, "require": { "ext-openssl": "*", "paragonie/random_compat": ">= 2", - "php": ">=5.4.0" + "php": ">=5.6.0" }, "require-dev": { - "nikic/php-parser": "^2.0|^3.0|^4.0", - "phpunit/phpunit": "^4|^5" + "phpunit/phpunit": "^4|^5|^6|^7|^8|^9" }, "bin": [ "bin/generate-defuse-key" @@ -1963,9 +2051,9 @@ ], "support": { "issues": "https://github.com/defuse/php-encryption/issues", - "source": "https://github.com/defuse/php-encryption/tree/master" + "source": "https://github.com/defuse/php-encryption/tree/v2.3.1" }, - "time": "2018-07-24T23:27:56+00:00" + "time": "2021-04-09T23:57:26+00:00" }, { "name": "doctrine/instantiator", @@ -2100,22 +2188,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.2.0", + "version": "7.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79" + "reference": "7008573787b430c1c1f650e3722d9bba59967628" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/0aa74dfb41ae110835923ef10a9d803a22d50e79", - "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628", + "reference": "7008573787b430c1c1f650e3722d9bba59967628", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/promises": "^1.4", - "guzzlehttp/psr7": "^1.7", + "guzzlehttp/psr7": "^1.7 || ^2.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0" }, @@ -2123,6 +2211,7 @@ "psr/http-client-implementation": "1.0" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", "ext-curl": "*", "php-http/client-integration-tests": "^3.0", "phpunit/phpunit": "^8.5.5 || ^9.3.5", @@ -2136,7 +2225,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.1-dev" + "dev-master": "7.3-dev" } }, "autoload": { @@ -2178,7 +2267,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.2.0" + "source": "https://github.com/guzzle/guzzle/tree/7.3.0" }, "funding": [ { @@ -2198,20 +2287,20 @@ "type": "github" } ], - "time": "2020-10-10T11:47:56+00:00" + "time": "2021-03-23T11:33:13+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "60d379c243457e073cff02bc323a2a86cb355631" + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/60d379c243457e073cff02bc323a2a86cb355631", - "reference": "60d379c243457e073cff02bc323a2a86cb355631", + "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", "shasum": "" }, "require": { @@ -2251,22 +2340,22 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.4.0" + "source": "https://github.com/guzzle/promises/tree/1.4.1" }, - "time": "2020-09-30T07:37:28+00:00" + "time": "2021-03-07T09:25:29+00:00" }, { "name": "guzzlehttp/psr7", - "version": "1.7.0", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3" + "reference": "dc960a912984efb74d0a90222870c72c87f10c91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/53330f47520498c0ae1f61f7e2c90f55690c06a3", - "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91", + "reference": "dc960a912984efb74d0a90222870c72c87f10c91", "shasum": "" }, "require": { @@ -2326,9 +2415,9 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.7.0" + "source": "https://github.com/guzzle/psr7/tree/1.8.2" }, - "time": "2020-09-30T07:37:11+00:00" + "time": "2021-04-26T09:17:50+00:00" }, { "name": "justinrainbow/json-schema", @@ -2400,87 +2489,6 @@ }, "time": "2020-05-27T16:41:55+00:00" }, - { - "name": "kriswallsmith/assetic", - "version": "v1.4.0", - "source": { - "type": "git", - "url": "https://github.com/kriswallsmith/assetic.git", - "reference": "e911c437dbdf006a8f62c2f59b15b2d69a5e0aa1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/e911c437dbdf006a8f62c2f59b15b2d69a5e0aa1", - "reference": "e911c437dbdf006a8f62c2f59b15b2d69a5e0aa1", - "shasum": "" - }, - "require": { - "php": ">=5.3.1", - "symfony/process": "~2.1|~3.0" - }, - "conflict": { - "twig/twig": "<1.27" - }, - "require-dev": { - "leafo/lessphp": "^0.3.7", - "leafo/scssphp": "~0.1", - "meenie/javascript-packer": "^1.1", - "mrclay/minify": "<2.3", - "natxet/cssmin": "3.0.4", - "patchwork/jsqueeze": "~1.0|~2.0", - "phpunit/phpunit": "~4.8 || ^5.6", - "psr/log": "~1.0", - "ptachoire/cssembed": "~1.0", - "symfony/phpunit-bridge": "~2.7|~3.0", - "twig/twig": "~1.23|~2.0", - "yfix/packager": "dev-master" - }, - "suggest": { - "leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler", - "leafo/scssphp": "Assetic provides the integration with the scssphp SCSS compiler", - "leafo/scssphp-compass": "Assetic provides the integration with the SCSS compass plugin", - "patchwork/jsqueeze": "Assetic provides the integration with the JSqueeze JavaScript compressor", - "ptachoire/cssembed": "Assetic provides the integration with phpcssembed to embed data uris", - "twig/twig": "Assetic provides the integration with the Twig templating engine" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-0": { - "Assetic": "src/" - }, - "files": [ - "src/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kris Wallsmith", - "email": "kris.wallsmith@gmail.com", - "homepage": "http://kriswallsmith.net/" - } - ], - "description": "Asset Management for PHP", - "homepage": "https://github.com/kriswallsmith/assetic", - "keywords": [ - "assets", - "compression", - "minification" - ], - "support": { - "issues": "https://github.com/kriswallsmith/assetic/issues", - "source": "https://github.com/kriswallsmith/assetic/tree/master" - }, - "time": "2016-11-11T18:43:20+00:00" - }, { "name": "maximebf/debugbar", "version": "v1.16.5", @@ -2606,16 +2614,16 @@ }, { "name": "nesbot/carbon", - "version": "2.45.1", + "version": "2.48.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "528783b188bdb853eb21239b1722831e0f000a8d" + "reference": "d3c447f21072766cddec3522f9468a5849a76147" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/528783b188bdb853eb21239b1722831e0f000a8d", - "reference": "528783b188bdb853eb21239b1722831e0f000a8d", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d3c447f21072766cddec3522f9468a5849a76147", + "reference": "d3c447f21072766cddec3522f9468a5849a76147", "shasum": "" }, "require": { @@ -2695,20 +2703,20 @@ "type": "tidelift" } ], - "time": "2021-02-11T18:30:17+00:00" + "time": "2021-05-07T10:08:30+00:00" }, { "name": "nikic/php-parser", - "version": "v4.10.4", + "version": "v4.10.5", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e" + "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4432ba399e47c66624bc73c8c0f811e5c109576f", + "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f", "shasum": "" }, "require": { @@ -2749,9 +2757,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.5" }, - "time": "2020-12-20T10:01:03+00:00" + "time": "2021-05-03T19:11:20+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -2876,24 +2884,26 @@ "source": { "type": "git", "url": "https://github.com/pckg-app/frontend-dev.git", - "reference": "0d4ff7eb2677b39e00f25afa9ae1b3f7c7d37130" + "reference": "9f76de112d9e35455de58df20b23dae618791dc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg-app/frontend-dev/zipball/0d4ff7eb2677b39e00f25afa9ae1b3f7c7d37130", - "reference": "0d4ff7eb2677b39e00f25afa9ae1b3f7c7d37130", + "url": "https://api.github.com/repos/pckg-app/frontend-dev/zipball/9f76de112d9e35455de58df20b23dae618791dc2", + "reference": "9f76de112d9e35455de58df20b23dae618791dc2", "shasum": "" }, "require": { - "appzcoder/phpcloc": "^0.0.2", "codeception/codeception": "4.*", "codeception/module-asserts": "1.*", - "codeception/module-phpbrowser": "^1.0", + "codeception/module-db": "1.*", + "codeception/module-phpbrowser": "1.*", + "codeception/module-redis": "1.*", "codeception/module-rest": "^1.2", - "codeception/module-webdriver": "dev-master", + "codeception/module-webdriver": "1.*", + "codeception/specify": "^1.4", "maximebf/debugbar": "^1.16", - "phpstan/phpstan": "^0.12.42", - "phpstan/phpstan-strict-rules": "^0.12.5", + "phpstan/phpstan": "^0.12.82", + "phpstan/phpstan-strict-rules": "^0.12.9", "squizlabs/php_codesniffer": "^3.5" }, "default-branch": true, @@ -2914,7 +2924,7 @@ "issues": "https://github.com/pckg-app/frontend-dev/issues", "source": "https://github.com/pckg-app/frontend-dev/tree/master" }, - "time": "2021-02-08T10:09:10+00:00" + "time": "2021-03-26T17:18:04+00:00" }, { "name": "pckg/auth", @@ -2922,18 +2932,18 @@ "source": { "type": "git", "url": "https://github.com/pckg/auth.git", - "reference": "2743d3a706770122e6160bb70c02f12f82eeadef" + "reference": "148b47cdcf97e9b10834871c93dbe9361bbb7879" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/auth/zipball/2743d3a706770122e6160bb70c02f12f82eeadef", - "reference": "2743d3a706770122e6160bb70c02f12f82eeadef", + "url": "https://api.github.com/repos/pckg/auth/zipball/148b47cdcf97e9b10834871c93dbe9361bbb7879", + "reference": "148b47cdcf97e9b10834871c93dbe9361bbb7879", "shasum": "" }, "require": { "ext-json": "*", "facebook/graph-sdk": "5.*", - "pckg/framework": "dev-master" + "pckg/framework": "dev-master || dev-master-yoda" }, "require-dev": { "facebook/facebook-instant-articles-sdk-php": "dev-master", @@ -2969,7 +2979,7 @@ "issues": "https://github.com/pckg/auth/issues", "source": "https://github.com/pckg/auth/tree/master" }, - "time": "2021-02-13T23:35:15+00:00" + "time": "2021-05-22T09:45:11+00:00" }, { "name": "pckg/htmlbuilder", @@ -2977,20 +2987,20 @@ "source": { "type": "git", "url": "https://github.com/pckg/htmlbuilder.git", - "reference": "ca4153a52f8438c44073cba43bc7324acaf116de" + "reference": "618286089d9f6740c80f15bed899a4b9cba0fe19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/htmlbuilder/zipball/ca4153a52f8438c44073cba43bc7324acaf116de", - "reference": "ca4153a52f8438c44073cba43bc7324acaf116de", + "url": "https://api.github.com/repos/pckg/htmlbuilder/zipball/618286089d9f6740c80f15bed899a4b9cba0fe19", + "reference": "618286089d9f6740c80f15bed899a4b9cba0fe19", "shasum": "" }, "require": { - "pckg/concept": "dev-master", - "pckg/framework": "dev-master" + "pckg/concept": "dev-master" }, "require-dev": { - "pckg-app/frontend-dev": "dev-master" + "pckg-app/frontend-dev": "dev-master", + "pckg/framework": "dev-master || dev-master-yoda" }, "default-branch": true, "type": "library", @@ -3020,7 +3030,7 @@ "issues": "https://github.com/pckg/htmlbuilder/issues", "source": "https://github.com/pckg/htmlbuilder/tree/master" }, - "time": "2021-02-06T17:41:35+00:00" + "time": "2021-05-22T09:48:19+00:00" }, { "name": "pckg/mail", @@ -3028,12 +3038,12 @@ "source": { "type": "git", "url": "https://github.com/pckg/mail.git", - "reference": "a68661a168979021234a9028c85de40986f179b0" + "reference": "bc8c05733a22f234b345c779e5abad6929b7e7bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/mail/zipball/a68661a168979021234a9028c85de40986f179b0", - "reference": "a68661a168979021234a9028c85de40986f179b0", + "url": "https://api.github.com/repos/pckg/mail/zipball/bc8c05733a22f234b345c779e5abad6929b7e7bf", + "reference": "bc8c05733a22f234b345c779e5abad6929b7e7bf", "shasum": "" }, "require": { @@ -3072,7 +3082,7 @@ "issues": "https://github.com/pckg/mail/issues", "source": "https://github.com/pckg/mail/tree/master" }, - "time": "2021-02-06T17:51:07+00:00" + "time": "2021-03-05T18:27:34+00:00" }, { "name": "pckg/manager", @@ -3080,16 +3090,16 @@ "source": { "type": "git", "url": "https://github.com/pckg/manager.git", - "reference": "82949dcb2702081e30db6f68e7f57ab94b9c63cb" + "reference": "03fffce1b8d7cde79e37f4b129200dab46356305" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/manager/zipball/82949dcb2702081e30db6f68e7f57ab94b9c63cb", - "reference": "82949dcb2702081e30db6f68e7f57ab94b9c63cb", + "url": "https://api.github.com/repos/pckg/manager/zipball/03fffce1b8d7cde79e37f4b129200dab46356305", + "reference": "03fffce1b8d7cde79e37f4b129200dab46356305", "shasum": "" }, "require": { - "kriswallsmith/assetic": "1.4.*" + "assetic/framework": "1.*" }, "require-dev": { "pckg-app/frontend-dev": "dev-master", @@ -3120,7 +3130,7 @@ "issues": "https://github.com/pckg/manager/issues", "source": "https://github.com/pckg/manager/tree/master" }, - "time": "2021-02-06T11:41:49+00:00" + "time": "2021-03-25T20:08:37+00:00" }, { "name": "pckg/migrator", @@ -3128,12 +3138,12 @@ "source": { "type": "git", "url": "https://github.com/pckg/migrator.git", - "reference": "85dba60102dca0cd0dc91fbbfbc435335ce5bd53" + "reference": "1887fb0b5b50b87989369180c8b540076ff10424" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/migrator/zipball/85dba60102dca0cd0dc91fbbfbc435335ce5bd53", - "reference": "85dba60102dca0cd0dc91fbbfbc435335ce5bd53", + "url": "https://api.github.com/repos/pckg/migrator/zipball/1887fb0b5b50b87989369180c8b540076ff10424", + "reference": "1887fb0b5b50b87989369180c8b540076ff10424", "shasum": "" }, "require": { @@ -3169,7 +3179,7 @@ "issues": "https://github.com/pckg/migrator/issues", "source": "https://github.com/pckg/migrator/tree/master" }, - "time": "2021-02-11T15:37:58+00:00" + "time": "2021-04-27T16:41:36+00:00" }, { "name": "pckg/queue", @@ -3177,12 +3187,12 @@ "source": { "type": "git", "url": "https://github.com/pckg/queue.git", - "reference": "2ce09e946a3e18d00579b02c3e708dd6420a82c0" + "reference": "a3f2ee378e95c0cb947aca4e6fef782a8f98385c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/queue/zipball/2ce09e946a3e18d00579b02c3e708dd6420a82c0", - "reference": "2ce09e946a3e18d00579b02c3e708dd6420a82c0", + "url": "https://api.github.com/repos/pckg/queue/zipball/a3f2ee378e95c0cb947aca4e6fef782a8f98385c", + "reference": "a3f2ee378e95c0cb947aca4e6fef782a8f98385c", "shasum": "" }, "require": { @@ -3223,7 +3233,7 @@ "issues": "https://github.com/pckg/queue/issues", "source": "https://github.com/pckg/queue/tree/master" }, - "time": "2021-02-06T18:18:17+00:00" + "time": "2021-03-23T21:40:00+00:00" }, { "name": "pckg/translator", @@ -3231,12 +3241,12 @@ "source": { "type": "git", "url": "https://github.com/pckg/translator.git", - "reference": "b230c08d891cec6fd5d8f8368970cb6e3dc038d8" + "reference": "512d1476a91e73a35dd40b33423b8784e1087aa7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pckg/translator/zipball/b230c08d891cec6fd5d8f8368970cb6e3dc038d8", - "reference": "b230c08d891cec6fd5d8f8368970cb6e3dc038d8", + "url": "https://api.github.com/repos/pckg/translator/zipball/512d1476a91e73a35dd40b33423b8784e1087aa7", + "reference": "512d1476a91e73a35dd40b33423b8784e1087aa7", "shasum": "" }, "require-dev": { @@ -3269,7 +3279,7 @@ "issues": "https://github.com/pckg/translator/issues", "source": "https://github.com/pckg/translator/tree/master" }, - "time": "2021-02-06T18:25:01+00:00" + "time": "2021-03-05T18:28:38+00:00" }, { "name": "phar-io/manifest", @@ -3333,16 +3343,16 @@ }, { "name": "phar-io/version", - "version": "3.0.4", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "e4782611070e50613683d2b9a57730e9a3ba5451" + "reference": "bae7c545bef187884426f042434e561ab1ddb182" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451", - "reference": "e4782611070e50613683d2b9a57730e9a3ba5451", + "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", + "reference": "bae7c545bef187884426f042434e561ab1ddb182", "shasum": "" }, "require": { @@ -3378,22 +3388,22 @@ "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.0.4" + "source": "https://github.com/phar-io/version/tree/3.1.0" }, - "time": "2020-12-13T23:18:30+00:00" + "time": "2021-02-23T14:00:09+00:00" }, { "name": "php-amqplib/php-amqplib", - "version": "2.12.2", + "version": "v2.12.3", "source": { "type": "git", "url": "https://github.com/php-amqplib/php-amqplib.git", - "reference": "199f89c377df6e7a52d127af63b7c52b4e677c6c" + "reference": "f746eb44df6d8f838173729867dd1d20b0265faa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/199f89c377df6e7a52d127af63b7c52b4e677c6c", - "reference": "199f89c377df6e7a52d127af63b7c52b4e677c6c", + "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/f746eb44df6d8f838173729867dd1d20b0265faa", + "reference": "f746eb44df6d8f838173729867dd1d20b0265faa", "shasum": "" }, "require": { @@ -3459,22 +3469,22 @@ ], "support": { "issues": "https://github.com/php-amqplib/php-amqplib/issues", - "source": "https://github.com/php-amqplib/php-amqplib/tree/2.12.2" + "source": "https://github.com/php-amqplib/php-amqplib/tree/v2.12.3" }, - "time": "2021-02-12T17:50:22+00:00" + "time": "2021-03-01T12:21:31+00:00" }, { "name": "php-webdriver/webdriver", - "version": "1.9.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/php-webdriver/php-webdriver.git", - "reference": "e3633154554605274cc9d59837f55a7427d72003" + "reference": "da16e39968f8dd5cfb7d07eef91dc2b731c69880" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/e3633154554605274cc9d59837f55a7427d72003", - "reference": "e3633154554605274cc9d59837f55a7427d72003", + "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/da16e39968f8dd5cfb7d07eef91dc2b731c69880", + "reference": "da16e39968f8dd5cfb7d07eef91dc2b731c69880", "shasum": "" }, "require": { @@ -3490,7 +3500,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.0", - "ondram/ci-detector": "^2.1 || ^3.5", + "ondram/ci-detector": "^2.1 || ^3.5 || ^4.0", "php-coveralls/php-coveralls": "^2.4", "php-mock/php-mock-phpunit": "^1.1 || ^2.0", "php-parallel-lint/php-parallel-lint": "^1.2", @@ -3502,11 +3512,6 @@ "ext-SimpleXML": "For Firefox profile creation" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.8.x-dev" - } - }, "autoload": { "psr-4": { "Facebook\\WebDriver\\": "lib/" @@ -3530,9 +3535,9 @@ ], "support": { "issues": "https://github.com/php-webdriver/php-webdriver/issues", - "source": "https://github.com/php-webdriver/php-webdriver/tree/1.9.0" + "source": "https://github.com/php-webdriver/php-webdriver/tree/1.11.1" }, - "time": "2020-11-19T15:21:05+00:00" + "time": "2021-05-21T15:12:49+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -3694,16 +3699,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.5", + "version": "3.0.8", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "7c751ea006577e4c2e83326d90c8b1e8c11b8ede" + "reference": "d9615a6fb970d9933866ca8b4036ec3407b020b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/7c751ea006577e4c2e83326d90c8b1e8c11b8ede", - "reference": "7c751ea006577e4c2e83326d90c8b1e8c11b8ede", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d9615a6fb970d9933866ca8b4036ec3407b020b6", + "reference": "d9615a6fb970d9933866ca8b4036ec3407b020b6", "shasum": "" }, "require": { @@ -3785,7 +3790,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.5" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.8" }, "funding": [ { @@ -3801,20 +3806,20 @@ "type": "tidelift" } ], - "time": "2021-02-12T16:18:16+00:00" + "time": "2021-04-19T03:20:48+00:00" }, { "name": "phpspec/prophecy", - "version": "1.12.2", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "245710e971a030f42e08f4912863805570f23d39" + "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/245710e971a030f42e08f4912863805570f23d39", - "reference": "245710e971a030f42e08f4912863805570f23d39", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea", + "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea", "shasum": "" }, "require": { @@ -3866,22 +3871,22 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.12.2" + "source": "https://github.com/phpspec/prophecy/tree/1.13.0" }, - "time": "2020-12-19T10:15:11+00:00" + "time": "2021-03-17T13:42:18+00:00" }, { "name": "phpstan/phpstan", - "version": "0.12.76", + "version": "0.12.88", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "7aaaf9a759a29795e8f46d48041af1c1f1b23d38" + "reference": "464d1a81af49409c41074aa6640ed0c4cbd9bb68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/7aaaf9a759a29795e8f46d48041af1c1f1b23d38", - "reference": "7aaaf9a759a29795e8f46d48041af1c1f1b23d38", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/464d1a81af49409c41074aa6640ed0c4cbd9bb68", + "reference": "464d1a81af49409c41074aa6640ed0c4cbd9bb68", "shasum": "" }, "require": { @@ -3912,7 +3917,7 @@ "description": "PHPStan - PHP Static Analysis Tool", "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/0.12.76" + "source": "https://github.com/phpstan/phpstan/tree/0.12.88" }, "funding": [ { @@ -3928,7 +3933,7 @@ "type": "tidelift" } ], - "time": "2021-02-13T11:47:44+00:00" + "time": "2021-05-17T12:24:49+00:00" }, { "name": "phpstan/phpstan-strict-rules", @@ -3983,16 +3988,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.5", + "version": "9.2.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1" + "reference": "f6293e1b30a2354e8428e004689671b83871edde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1", - "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde", + "reference": "f6293e1b30a2354e8428e004689671b83871edde", "shasum": "" }, "require": { @@ -4048,7 +4053,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.5" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6" }, "funding": [ { @@ -4056,7 +4061,7 @@ "type": "github" } ], - "time": "2020-11-28T06:44:49+00:00" + "time": "2021-03-28T07:26:59+00:00" }, { "name": "phpunit/php-file-iterator", @@ -4301,16 +4306,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.2", + "version": "9.5.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f661659747f2f87f9e72095bb207bceb0f151cb4" + "reference": "c73c6737305e779771147af66c96ca6a7ed8a741" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f661659747f2f87f9e72095bb207bceb0f151cb4", - "reference": "f661659747f2f87f9e72095bb207bceb0f151cb4", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c73c6737305e779771147af66c96ca6a7ed8a741", + "reference": "c73c6737305e779771147af66c96ca6a7ed8a741", "shasum": "" }, "require": { @@ -4388,7 +4393,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.2" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.4" }, "funding": [ { @@ -4400,34 +4405,36 @@ "type": "github" } ], - "time": "2021-02-02T14:45:58+00:00" + "time": "2021-03-23T07:16:29+00:00" }, { - "name": "psr/container", - "version": "1.0.0", + "name": "predis/predis", + "version": "v1.1.7", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "url": "https://github.com/predis/predis.git", + "reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/predis/predis/zipball/b240daa106d4e02f0c5b7079b41e31ddf66fddf8", + "reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3.9" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "ext-curl": "Allows access to Webdis when paired with phpiredis", + "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" }, + "type": "library", "autoload": { "psr-4": { - "Psr\\Container\\": "src/" + "Predis\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4436,11 +4443,70 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Daniele Alessandri", + "email": "suppakilla@gmail.com", + "homepage": "http://clorophilla.net", + "role": "Creator & Maintainer" + }, + { + "name": "Till Krüss", + "homepage": "https://till.im", + "role": "Maintainer" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", + "description": "Flexible and feature-complete Redis client for PHP and HHVM", + "homepage": "http://github.com/predis/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "support": { + "issues": "https://github.com/predis/predis/issues", + "source": "https://github.com/predis/predis/tree/v1.1.7" + }, + "funding": [ + { + "url": "https://github.com/sponsors/tillkruss", + "type": "github" + } + ], + "time": "2021-04-04T19:34:46+00:00" + }, + { + "name": "psr/container", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", "homepage": "https://github.com/php-fig/container", "keywords": [ "PSR-11", @@ -4451,9 +4517,59 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/master" + "source": "https://github.com/php-fig/container/tree/1.1.1" }, - "time": "2017-02-14T16:28:37+00:00" + "time": "2021-03-05T17:36:06+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" }, { "name": "psr/http-client", @@ -5739,25 +5855,22 @@ }, { "name": "softcreatr/jsonpath", - "version": "0.7.2", + "version": "0.7.4", "source": { "type": "git", "url": "https://github.com/SoftCreatR/JSONPath.git", - "reference": "46689608586a8081be399342755c36e179f3b5fc" + "reference": "e01ff3eae8d0b94648354cb02b614968e83d56a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SoftCreatR/JSONPath/zipball/46689608586a8081be399342755c36e179f3b5fc", - "reference": "46689608586a8081be399342755c36e179f3b5fc", + "url": "https://api.github.com/repos/SoftCreatR/JSONPath/zipball/e01ff3eae8d0b94648354cb02b614968e83d56a2", + "reference": "e01ff3eae8d0b94648354cb02b614968e83d56a2", "shasum": "" }, "require": { "ext-json": "*", "php": ">=7.1" }, - "conflict": { - "phpunit/phpunit": "<7.0 || >= 10.0" - }, "replace": { "flow/jsonpath": "*" }, @@ -5793,6 +5906,7 @@ "description": "JSONPath implementation for parsing, searching and flattening arrays", "support": { "email": "hello@1-2.dev", + "forum": "https://github.com/SoftCreatR/JSONPath/discussions", "issues": "https://github.com/SoftCreatR/JSONPath/issues", "source": "https://github.com/SoftCreatR/JSONPath" }, @@ -5802,20 +5916,20 @@ "type": "github" } ], - "time": "2020-10-27T11:37:08+00:00" + "time": "2021-05-07T14:31:33+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.8", + "version": "3.6.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4" + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", "shasum": "" }, "require": { @@ -5858,7 +5972,7 @@ "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2020-10-23T02:01:07+00:00" + "time": "2021-04-09T00:54:41+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -5920,16 +6034,16 @@ }, { "name": "symfony/browser-kit", - "version": "v5.2.3", + "version": "v5.2.9", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "b03b2057ed53ee4eab2e8f372084d7722b7b8ffd" + "reference": "38e16b426f1a4cd663b2583111f213e0c9d9d4fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/b03b2057ed53ee4eab2e8f372084d7722b7b8ffd", - "reference": "b03b2057ed53ee4eab2e8f372084d7722b7b8ffd", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/38e16b426f1a4cd663b2583111f213e0c9d9d4fe", + "reference": "38e16b426f1a4cd663b2583111f213e0c9d9d4fe", "shasum": "" }, "require": { @@ -5971,7 +6085,7 @@ "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/browser-kit/tree/v5.2.3" + "source": "https://github.com/symfony/browser-kit/tree/v5.2.9" }, "funding": [ { @@ -5987,46 +6101,48 @@ "type": "tidelift" } ], - "time": "2021-01-27T12:56:27+00:00" + "time": "2021-05-16T13:07:46+00:00" }, { "name": "symfony/console", - "version": "v4.4.19", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "24026c44fc37099fa145707fecd43672831b837a" + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/24026c44fc37099fa145707fecd43672831b837a", - "reference": "24026c44fc37099fa145707fecd43672831b837a", + "url": "https://api.github.com/repos/symfony/console/zipball/864568fdc0208b3eba3638b6000b69d2386e6768", + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", "symfony/polyfill-php80": "^1.15", - "symfony/service-contracts": "^1.1|^2" + "symfony/service-contracts": "^1.1|^2", + "symfony/string": "^5.1" }, "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/event-dispatcher": "<4.3|>=5", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", "symfony/lock": "<4.4", - "symfony/process": "<3.3" + "symfony/process": "<4.4" }, "provide": { "psr/log-implementation": "1.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/event-dispatcher": "^4.3", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", "symfony/lock": "^4.4|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", - "symfony/var-dumper": "^4.3|^5.0" + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" }, "suggest": { "psr/log": "For using the console logger", @@ -6059,8 +6175,14 @@ ], "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], "support": { - "source": "https://github.com/symfony/console/tree/v4.4.19" + "source": "https://github.com/symfony/console/tree/v5.2.8" }, "funding": [ { @@ -6076,20 +6198,20 @@ "type": "tidelift" } ], - "time": "2021-01-27T09:09:26+00:00" + "time": "2021-05-11T15:45:21+00:00" }, { "name": "symfony/css-selector", - "version": "v5.2.3", + "version": "v5.2.9", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "f65f217b3314504a1ec99c2d6ef69016bb13490f" + "reference": "5d5f97809015102116208b976eb2edb44b689560" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/f65f217b3314504a1ec99c2d6ef69016bb13490f", - "reference": "f65f217b3314504a1ec99c2d6ef69016bb13490f", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/5d5f97809015102116208b976eb2edb44b689560", + "reference": "5d5f97809015102116208b976eb2edb44b689560", "shasum": "" }, "require": { @@ -6125,7 +6247,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.2.3" + "source": "https://github.com/symfony/css-selector/tree/v5.2.9" }, "funding": [ { @@ -6141,20 +6263,20 @@ "type": "tidelift" } ], - "time": "2021-01-27T10:01:46+00:00" + "time": "2021-05-16T13:07:46+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665" + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665", - "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627", "shasum": "" }, "require": { @@ -6163,7 +6285,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -6192,7 +6314,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/master" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" }, "funding": [ { @@ -6208,20 +6330,20 @@ "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2021-03-23T23:28:01+00:00" }, { "name": "symfony/dom-crawler", - "version": "v5.2.3", + "version": "v5.2.9", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "5d89ceb53ec65e1973a555072fac8ed5ecad3384" + "reference": "8d5201206ded6f37de475b041a11bfaf3ac73d5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/5d89ceb53ec65e1973a555072fac8ed5ecad3384", - "reference": "5d89ceb53ec65e1973a555072fac8ed5ecad3384", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/8d5201206ded6f37de475b041a11bfaf3ac73d5e", + "reference": "8d5201206ded6f37de475b041a11bfaf3ac73d5e", "shasum": "" }, "require": { @@ -6266,7 +6388,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v5.2.3" + "source": "https://github.com/symfony/dom-crawler/tree/v5.2.9" }, "funding": [ { @@ -6282,42 +6404,44 @@ "type": "tidelift" } ], - "time": "2021-01-27T10:01:46+00:00" + "time": "2021-05-16T13:07:46+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.4.19", + "version": "v5.2.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "c352647244bd376bf7d31efbd5401f13f50dad0c" + "reference": "d08d6ec121a425897951900ab692b612a61d6240" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c352647244bd376bf7d31efbd5401f13f50dad0c", - "reference": "c352647244bd376bf7d31efbd5401f13f50dad0c", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d08d6ec121a425897951900ab692b612a61d6240", + "reference": "d08d6ec121a425897951900ab692b612a61d6240", "shasum": "" }, "require": { - "php": ">=7.1.3", - "symfony/event-dispatcher-contracts": "^1.1" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/event-dispatcher-contracts": "^2", + "symfony/polyfill-php80": "^1.15" }, "conflict": { - "symfony/dependency-injection": "<3.4" + "symfony/dependency-injection": "<4.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "1.1" + "symfony/event-dispatcher-implementation": "2.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/error-handler": "~3.4|~4.4", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/http-foundation": "^3.4|^4.0|^5.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^3.4|^4.0|^5.0" + "symfony/stopwatch": "^4.4|^5.0" }, "suggest": { "symfony/dependency-injection": "", @@ -6349,7 +6473,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.19" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.2.4" }, "funding": [ { @@ -6365,33 +6489,33 @@ "type": "tidelift" } ], - "time": "2021-01-27T09:09:26+00:00" + "time": "2021-02-18T17:12:37+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.9", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7" + "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/84e23fdcd2517bf37aecbd16967e83f0caee25a7", - "reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/69fee1ad2332a7cbab3aca13591953da9cdb7a11", + "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11", "shasum": "" }, "require": { - "php": ">=7.1.3" + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" }, "suggest": { - "psr/event-dispatcher": "", "symfony/event-dispatcher-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -6428,7 +6552,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.9" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.4.0" }, "funding": [ { @@ -6444,20 +6568,20 @@ "type": "tidelift" } ], - "time": "2020-07-06T13:19:58+00:00" + "time": "2021-03-23T23:28:01+00:00" }, { "name": "symfony/finder", - "version": "v5.2.3", + "version": "v5.2.9", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "4adc8d172d602008c204c2e16956f99257248e03" + "reference": "ccccb9d48ca42757dd12f2ca4bf857a4e217d90d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/4adc8d172d602008c204c2e16956f99257248e03", - "reference": "4adc8d172d602008c204c2e16956f99257248e03", + "url": "https://api.github.com/repos/symfony/finder/zipball/ccccb9d48ca42757dd12f2ca4bf857a4e217d90d", + "reference": "ccccb9d48ca42757dd12f2ca4bf857a4e217d90d", "shasum": "" }, "require": { @@ -6489,7 +6613,88 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.2.3" + "source": "https://github.com/symfony/finder/tree/v5.2.9" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-16T13:07:46+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5601e09b69f26c1828b13b6bb87cb07cddba3170", + "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1" }, "funding": [ { @@ -6505,20 +6710,104 @@ "type": "tidelift" } ], - "time": "2021-01-28T22:06:19+00:00" + "time": "2021-01-22T09:19:47+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/43a0283138253ed1d48d352ab6d0bdb3f809f248", + "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-22T09:19:47+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.22.0", + "version": "v1.22.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13" + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", - "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1", + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1", "shasum": "" }, "require": { @@ -6569,7 +6858,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" }, "funding": [ { @@ -6585,11 +6874,11 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-01-22T09:19:47+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.22.0", + "version": "v1.22.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", @@ -6648,7 +6937,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" }, "funding": [ { @@ -6668,7 +6957,7 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.22.0", + "version": "v1.22.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", @@ -6731,7 +7020,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" }, "funding": [ { @@ -6751,20 +7040,21 @@ }, { "name": "symfony/process", - "version": "v3.4.47", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca" + "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/b8648cf1d5af12a44a51d07ef9bf980921f15fca", - "reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca", + "url": "https://api.github.com/repos/symfony/process/zipball/98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e", + "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.15" }, "type": "library", "autoload": { @@ -6789,10 +7079,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Process Component", + "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v3.4.47" + "source": "https://github.com/symfony/process/tree/v5.3.0-BETA1" }, "funding": [ { @@ -6808,25 +7098,25 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2021-04-08T10:27:02+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1" + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", "shasum": "" }, "require": { "php": ">=7.2.5", - "psr/container": "^1.0" + "psr/container": "^1.1" }, "suggest": { "symfony/service-implementation": "" @@ -6834,7 +7124,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -6871,7 +7161,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/master" + "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" }, "funding": [ { @@ -6887,20 +7177,103 @@ "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2021-04-01T10:43:52+00:00" + }, + { + "name": "symfony/string", + "version": "v5.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "files": [ + "Resources/functions.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.2.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-10T14:56:10+00:00" }, { "name": "symfony/translation", - "version": "v5.2.3", + "version": "v5.2.9", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "c021864d4354ee55160ddcfd31dc477a1bc77949" + "reference": "61af68dba333e2d376a325a29c2a3f2a605b4876" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/c021864d4354ee55160ddcfd31dc477a1bc77949", - "reference": "c021864d4354ee55160ddcfd31dc477a1bc77949", + "url": "https://api.github.com/repos/symfony/translation/zipball/61af68dba333e2d376a325a29c2a3f2a605b4876", + "reference": "61af68dba333e2d376a325a29c2a3f2a605b4876", "shasum": "" }, "require": { @@ -6917,7 +7290,7 @@ "symfony/yaml": "<4.4" }, "provide": { - "symfony/translation-implementation": "2.0" + "symfony/translation-implementation": "2.3" }, "require-dev": { "psr/log": "~1.0", @@ -6964,7 +7337,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.2.3" + "source": "https://github.com/symfony/translation/tree/v5.2.9" }, "funding": [ { @@ -6980,20 +7353,20 @@ "type": "tidelift" } ], - "time": "2021-01-27T10:15:41+00:00" + "time": "2021-05-16T13:07:46+00:00" }, { "name": "symfony/translation-contracts", - "version": "v2.3.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "e2eaa60b558f26a4b0354e1bbb25636efaaad105" + "reference": "95c812666f3e91db75385749fe219c5e494c7f95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/e2eaa60b558f26a4b0354e1bbb25636efaaad105", - "reference": "e2eaa60b558f26a4b0354e1bbb25636efaaad105", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95", + "reference": "95c812666f3e91db75385749fe219c5e494c7f95", "shasum": "" }, "require": { @@ -7005,7 +7378,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -7042,7 +7415,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.3.0" + "source": "https://github.com/symfony/translation-contracts/tree/v2.4.0" }, "funding": [ { @@ -7058,20 +7431,20 @@ "type": "tidelift" } ], - "time": "2020-09-28T13:05:58+00:00" + "time": "2021-03-23T23:28:01+00:00" }, { "name": "symfony/var-dumper", - "version": "v5.2.3", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "72ca213014a92223a5d18651ce79ef441c12b694" + "reference": "d693200a73fae179d27f8f1b16b4faf3e8569eba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/72ca213014a92223a5d18651ce79ef441c12b694", - "reference": "72ca213014a92223a5d18651ce79ef441c12b694", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d693200a73fae179d27f8f1b16b4faf3e8569eba", + "reference": "d693200a73fae179d27f8f1b16b4faf3e8569eba", "shasum": "" }, "require": { @@ -7130,7 +7503,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.2.3" + "source": "https://github.com/symfony/var-dumper/tree/v5.2.8" }, "funding": [ { @@ -7146,20 +7519,20 @@ "type": "tidelift" } ], - "time": "2021-01-27T10:15:41+00:00" + "time": "2021-05-07T13:42:21+00:00" }, { "name": "symfony/yaml", - "version": "v5.2.3", + "version": "v5.2.9", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "338cddc6d74929f6adf19ca5682ac4b8e109cdb0" + "reference": "d23115e4a3d50520abddccdbec9514baab1084c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/338cddc6d74929f6adf19ca5682ac4b8e109cdb0", - "reference": "338cddc6d74929f6adf19ca5682ac4b8e109cdb0", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d23115e4a3d50520abddccdbec9514baab1084c8", + "reference": "d23115e4a3d50520abddccdbec9514baab1084c8", "shasum": "" }, "require": { @@ -7205,7 +7578,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.2.3" + "source": "https://github.com/symfony/yaml/tree/v5.2.9" }, "funding": [ { @@ -7221,7 +7594,7 @@ "type": "tidelift" } ], - "time": "2021-02-03T04:42:09+00:00" + "time": "2021-05-16T13:07:46+00:00" }, { "name": "theseer/tokenizer", @@ -7275,30 +7648,35 @@ }, { "name": "webmozart/assert", - "version": "1.9.1", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", + "php": "^7.2 || ^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" + "vimeo/psalm": "<4.6.1 || 4.6.2" }, "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" + "phpunit/phpunit": "^8.5.13" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -7322,9 +7700,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.9.1" + "source": "https://github.com/webmozarts/assert/tree/1.10.0" }, - "time": "2020-07-08T17:02:28+00:00" + "time": "2021-03-09T10:59:23+00:00" } ], "aliases": [], @@ -7348,7 +7726,10 @@ }, "prefer-stable": true, "prefer-lowest": false, - "platform": [], + "platform": { + "ext-json": "*", + "ext-pcntl": "*" + }, "platform-dev": [], "plugin-api-version": "2.0.0" } diff --git a/config/defaults.php b/config/defaults.php new file mode 100644 index 00000000..3d866322 --- /dev/null +++ b/config/defaults.php @@ -0,0 +1,13 @@ + [ + 'apps' => [ + 'test' => [ + 'host' => [ + '(.*)', + ], + ], + ], + ], +]; diff --git a/ruleset.xml b/ruleset.xml new file mode 100644 index 00000000..d5c7f80d --- /dev/null +++ b/ruleset.xml @@ -0,0 +1,8 @@ + + + The PSR-12* coding standard. + + + + + diff --git a/src/Pckg/Framework/Application.php b/src/Pckg/Framework/Application.php index 6d4204a5..39f9b832 100644 --- a/src/Pckg/Framework/Application.php +++ b/src/Pckg/Framework/Application.php @@ -2,7 +2,7 @@ namespace Pckg\Framework; -use Pckg\Framework\Application\ApplicationInterface; +use Pckg\Framework\Config\Command\InitConfig; use Pckg\Framework\Provider\Helper\Registrator; class Application @@ -11,6 +11,8 @@ class Application protected $provider; + const EVENT_REGISTERED = self::class . '.registered'; + public function __construct(Provider $provider) { $this->provider = $provider; @@ -25,7 +27,7 @@ public function initAndRun() { /** * Initialize application. - * This will parse config, set localization 'things', estamblish connection to database, initialize and register + * This will parse config, set localization 'things', establish connection to database, initialize and register * routes, set application autoloaders and providers, session, response, request and assets. */ measure('Initializing ' . static::class, function () { diff --git a/src/Pckg/Framework/Application/Command/InitDatabase.php b/src/Pckg/Framework/Application/Command/InitDatabase.php index 860ec70c..62257ced 100644 --- a/src/Pckg/Framework/Application/Command/InitDatabase.php +++ b/src/Pckg/Framework/Application/Command/InitDatabase.php @@ -3,15 +3,23 @@ namespace Pckg\Framework\Application\Command; use Pckg\Database\Repository\RepositoryFactory; +use Pckg\Framework\Config; class InitDatabase { + protected Config $config; + + public function __construct(Config $config) + { + $this->config = $config; + } + public function execute(callable $next) { - foreach (config('database', []) as $name => $config) { + foreach ($this->config->get('database', []) as $name => $config) { /** - * Skip lazy initialize connections which will be estamblished on demand. + * Skip lazy initialize connections which will be established on demand. */ if (is_string($config) || ($config['lazy'] ?? false)) { continue; diff --git a/src/Pckg/Framework/Application/Command/InitEvents.php b/src/Pckg/Framework/Application/Command/InitEvents.php new file mode 100644 index 00000000..53d6c4bd --- /dev/null +++ b/src/Pckg/Framework/Application/Command/InitEvents.php @@ -0,0 +1,28 @@ +config = $config; + } + + public function execute(callable $next) + { + $globalEvents = $this->config->get('pckg.dispatcher.events', []); + collect($globalEvents)->each(fn($handlers, $event) => collect($handlers)->each(fn($handler) => dispatcher()->listen($event, $handler))); + + trigger(InitEvents::class . '.executed'); + + return $next(); + } +} diff --git a/src/Pckg/Framework/Application/Command/RegisterApplication.php b/src/Pckg/Framework/Application/Command/RegisterApplication.php index 277ffdc5..b1faf239 100644 --- a/src/Pckg/Framework/Application/Command/RegisterApplication.php +++ b/src/Pckg/Framework/Application/Command/RegisterApplication.php @@ -2,7 +2,9 @@ namespace Pckg\Framework\Application\Command; +use Pckg\Concept\Event\Dispatcher; use Pckg\Framework\Application; +use Pckg\Framework\Config; use Pckg\Framework\Provider\Helper\Registrator; use Pckg\Locale\Command\Localize; @@ -10,11 +12,17 @@ class RegisterApplication { use Registrator; + protected Application $application; - protected $application; - public function __construct(Application $application) + protected Config $config; + + protected Dispatcher $dispatcher; + + public function __construct(Application $application, Config $config, Dispatcher $dispatcher) { $this->application = $application; + $this->config = $config; + $this->dispatcher = $dispatcher; } public function execute(callable $next) @@ -23,20 +31,27 @@ public function execute(callable $next) * Register main application provider. */ $this->application->getProvider()->register(); -// 0.44 -> 0.97 / 1.03 = 0.53s = 50% + // 0.44 -> 0.97 / 1.03 = 0.53s = 50% /** - * Parse application config. + * (Re)Parse application config? Becaaaaause? + * @deprecated + * If this needs to be reactivated, hook this to EVENT_REGISTERED ? + * Do we always want to re-read config and re-localize when providers are registered? + * Okay for Localize? No for InitConfig? Shouldn't they be able to change config in runtime? */ - config()->parseDir(path('app')); -/** + resolve(Config\Command\InitConfig::class)->execute(function() {}); + + /** * Localize any config changes. */ chain([Localize::class]); -/** + + /** * Trigger event. */ - trigger(Application::class . '.registered'); + $this->dispatcher->trigger(Application::EVENT_REGISTERED); + return $next(); } } diff --git a/src/Pckg/Framework/Application/Console/Command/RunCommand.php b/src/Pckg/Framework/Application/Console/Command/RunCommand.php index 462c46df..8ceddd99 100644 --- a/src/Pckg/Framework/Application/Console/Command/RunCommand.php +++ b/src/Pckg/Framework/Application/Console/Command/RunCommand.php @@ -3,24 +3,32 @@ namespace Pckg\Framework\Application\Console\Command; use Pckg\Concept\AbstractChainOfReponsibility; +use Pckg\Concept\Event\Dispatcher; +use Pckg\Framework\Request\Data\Server; use Pckg\Framework\Response; -use Symfony\Component\Console\Application; use Symfony\Component\Console\Application as SymfonyConsole; -use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; use Throwable; class RunCommand extends AbstractChainOfReponsibility { - protected $response; + protected Response $response; - public function __construct(Response $response) + protected Dispatcher $dispatcher; + + protected SymfonyConsole $symfonyConsole; + + protected Server $server; + + const EVENT_RUNNING = self::class . '.running'; + + public function __construct(Response $response, Dispatcher $dispatcher, SymfonyConsole $symfonyConsole, Server $server) { $this->response = $response; + $this->dispatcher = $dispatcher; + $this->symfonyConsole = $symfonyConsole; + $this->server = $server; } public function execute(callable $next) @@ -32,7 +40,7 @@ public function execute(callable $next) * If it's command, we leave things as they are. * Id it's app, we unset it. */ - $argv = $_SERVER['argv']; + $argv = $this->server->get('argv', []); /** * Remove application name. @@ -44,13 +52,11 @@ public function execute(callable $next) /** * Trigger event */ - trigger(RunCommand::class . '.running', []); + $this->dispatcher->trigger(static::EVENT_RUNNING, []); /** * Get Symfony Console Application, find available commands and run app. - * @var SymfonyConsole $application */ - $application = context()->get(SymfonyConsole::class); try { /** * Apply global middlewares. @@ -59,7 +65,7 @@ public function execute(callable $next) chain($middlewares, 'execute'); } - $application->run(new ArgvInput(array_values($argv))); + $this->symfonyConsole->run(new ArgvInput(array_values($argv)), context()->getOrDefault(RunCommand::class . '.output')); /** * Apply global afterwares/decorators. @@ -68,14 +74,10 @@ public function execute(callable $next) chain($afterwares, 'execute', [$this->response]); } } catch (Throwable $e) { - die("EXCEPTION: " . exception($e)); + die("EXCEPTION: " . \Pckg\Framework\Helper\exception($e)); } - - /** - * This is here just for better readability. =) - */ - echo "\n"; } catch (Throwable $e) { + error_log(\Pckg\Framework\Helper\exception($e)); } return $next(); diff --git a/src/Pckg/Framework/Application/Website.php b/src/Pckg/Framework/Application/Website.php index 9293ca45..9d07e3f7 100644 --- a/src/Pckg/Framework/Application/Website.php +++ b/src/Pckg/Framework/Application/Website.php @@ -4,10 +4,12 @@ use Pckg\Framework\Application; use Pckg\Framework\Application\Command\InitDatabase; +use Pckg\Framework\Application\Command\InitEvents; use Pckg\Framework\Application\Command\RegisterApplication; use Pckg\Framework\Application\Website\Command\InitLastAssets; use Pckg\Framework\Config\Command\InitConfig; use Pckg\Framework\Request\Command\InitRequest; +use Pckg\Framework\Request\Command\InitRoute; use Pckg\Framework\Request\Command\RunRequest; use Pckg\Framework\Request\Session\Command\InitSession; use Pckg\Framework\Response\Command\InitResponse; @@ -28,15 +30,17 @@ public function inits() { return [ InitConfig::class, + InitRequest::class, + InitResponse::class, + InitEvents::class, Localize::class, InitRouter::class, InitDatabase::class, // can we init it on demand? - InitSession::class, // can we init it on demand? RegisterApplication::class, - InitResponse::class, - InitRequest::class, + InitRoute::class, + InitSession::class, // can we init it on demand? ]; } @@ -44,7 +48,6 @@ public function runs() { return [ RunRequest::class, - InitLastAssets::class, RunResponse::class, ]; } diff --git a/src/Pckg/Framework/Application/Website/Command/InitLastAssets.php b/src/Pckg/Framework/Application/Website/Command/InitLastAssets.php index 49a66ab8..f015ee85 100644 --- a/src/Pckg/Framework/Application/Website/Command/InitLastAssets.php +++ b/src/Pckg/Framework/Application/Website/Command/InitLastAssets.php @@ -6,6 +6,11 @@ use Pckg\Framework\Environment; use Pckg\Manager\Asset as AssetManager; +/** + * Class InitLastAssets + * @package Pckg\Framework\Application\Website\Command + * @deprecated + */ class InitLastAssets extends AbstractChainOfReponsibility { @@ -13,10 +18,8 @@ class InitLastAssets extends AbstractChainOfReponsibility protected $environment; - public function __construct( - Environment $environment, - AssetManager $assetManager - ) { + public function __construct(Environment $environment, AssetManager $assetManager) + { $this->assetManager = $assetManager; $this->environment = $environment; } diff --git a/src/Pckg/Framework/Config.php b/src/Pckg/Framework/Config.php index 014d8c53..e2468635 100644 --- a/src/Pckg/Framework/Config.php +++ b/src/Pckg/Framework/Config.php @@ -7,6 +7,10 @@ class Config protected $data = []; + protected $registeredDirs = []; + + const EVENT_DIR_PARSED = self::class . '.dirParsed'; + public function __construct(array $data = []) { $this->overwrite($data); @@ -55,6 +59,31 @@ public function set($key, $val, $merge = true) $this->data = $this->setRecursive($keys, $val, $this->data, 0, $merge); } + public function apply(array $config) + { + $dotted = $this->toDotted($config); + foreach ($dotted as $key => $val) { + $this->set($key, $val); + } + + return $dotted; + } + + public function toDotted($config, string $parentKey = null, &$dotted = []) + { + if (!is_array($config)) { + $dotted[$parentKey] = $config; + return; + } + + foreach ($config as $key => $val) { + $newKey = $parentKey ? $parentKey . '.' . $key : $key; + $this->toDotted($val, $newKey, $dotted); + } + + return $dotted; + } + private function setRecursive($keys, $val, $data, $i, $merge = true) { if (!is_array($data)) { @@ -95,6 +124,11 @@ private function setRecursive($keys, $val, $data, $i, $merge = true) return $data; } + public function hasRegisteredDir($dir): bool + { + return in_array($dir, $this->registeredDirs); + } + public function parseDir($dir) { if (!$dir) { @@ -113,6 +147,11 @@ public function parseDir($dir) $this->data = merge_arrays($this->data, $settings); + /** + * @T00D00 - move this to the event handler + */ + $this->registeredDirs[] = $dir; + trigger(static::EVENT_DIR_PARSED, [$this]); $this->set('url', "https://" . config('domain')); } @@ -122,17 +161,17 @@ protected function parseFiles($files) foreach ( [ - function ($file) { - return strpos($file, '/defaults.php'); - }, - function ($file) { - return !strpos($file, '/defaults.php') && !strpos($file, '/env.php') && - !strpos($file, '/migrations.php'); - }, - function ($file) { - return strpos($file, '/env.php'); - }, - ] as $callback + function ($file) { + return strpos($file, '/defaults.php'); + }, + function ($file) { + return !strpos($file, '/defaults.php') && !strpos($file, '/env.php') && + !strpos($file, '/migrations.php'); + }, + function ($file) { + return strpos($file, '/env.php'); + }, + ] as $callback ) { foreach ($files as $key => $file) { if (!$callback($file)) { diff --git a/src/Pckg/Framework/Config/Command/InitConfig.php b/src/Pckg/Framework/Config/Command/InitConfig.php index 7252ac93..aea2e9c9 100644 --- a/src/Pckg/Framework/Config/Command/InitConfig.php +++ b/src/Pckg/Framework/Config/Command/InitConfig.php @@ -20,7 +20,11 @@ public function __construct(Config $config) public function execute(callable $next) { - $this->config->parseDir(path('app')); + if ($this->config->get('path.app')) { + $this->config->parseDir(path('app')); + } + + trigger(InitConfig::class . '.executed'); return $next(); } diff --git a/src/Pckg/Framework/Console/Command/DeployProject.php b/src/Pckg/Framework/Console/Command/DeployProject.php index 22ab17e7..a4b2dd58 100644 --- a/src/Pckg/Framework/Console/Command/DeployProject.php +++ b/src/Pckg/Framework/Console/Command/DeployProject.php @@ -30,9 +30,9 @@ public function handle() $this->output('Happy FRIDAY deploy!'); } - $this->output('Estamblishing SSH connection to ' . $remote['host'] . '.'); + $this->output('Establishing SSH connection to ' . $remote['host'] . '.'); $sshConnection = ssh2_connect($remote['host'], $remote['port']); - $this->output('SSH connection estamblished.'); + $this->output('SSH connection established.'); /** * Authenticate with username and password or username and key. @@ -41,12 +41,12 @@ public function handle() if ( !ssh2_auth_password($sshConnection, $remote['username'], $remote['password']) ) { - throw new Exception('Cannot estamblish SSH connection to remote with username and password'); + throw new Exception('Cannot establish SSH connection to remote with username and password'); } } elseif ( !ssh2_auth_pubkey_file($sshConnection, $remote['username'], $remote['key'] . '.pub', $remote['key'], '') ) { - throw new Exception('Cannot estamblish SSH connection to remote with username and key'); + throw new Exception('Cannot establish SSH connection to remote with username and key'); } $paths = $remote['root']; diff --git a/src/Pckg/Framework/Console/Command/InitProject.php b/src/Pckg/Framework/Console/Command/InitProject.php index 12e32793..690a954b 100644 --- a/src/Pckg/Framework/Console/Command/InitProject.php +++ b/src/Pckg/Framework/Console/Command/InitProject.php @@ -40,7 +40,7 @@ public function dirs() public function files() { return [ - 'pckg.json' => '[]', + // 'pckg.json' => '[]', ]; } @@ -82,9 +82,18 @@ public function createFiles() public function copyConfigs() { + $env = $this->option('env', 'docker'); $files = [ - 'codeception.sample.yml' => 'codeception.yml', + 'codeception.sample.yml' => 'codeception.yml', + '.env.' . $env => '.env', '.env.example' => '.env', + '.env.database.' . $env => '.env.database', + '.env.redis.' . $env => '.env.redis', + '.env.queue.' . $env => '.env.queue', + '.env.rabbit.' . $env => '.env.rabbit', + '.env.cache.' . $env => '.env.cache', + '.env.web.' . $env => '.env.web', + '.env.www.' . $env => '.env.www', ]; if ($app = $this->option('app')) { @@ -119,6 +128,7 @@ protected function configure() { $this->setName('project:init') ->setDescription('Initialize project (create required directories and configs)') - ->addOption('app', 'app', InputArgument::OPTIONAL, 'Init app structure and configs'); + ->addOption('app', 'app', InputArgument::OPTIONAL, 'Init app structure and configs') + ->addOption('env', 'env', InputArgument::OPTIONAL, 'Default = docker'); } } diff --git a/src/Pckg/Framework/Environment.php b/src/Pckg/Framework/Environment.php index 07df5935..57b06d3f 100644 --- a/src/Pckg/Framework/Environment.php +++ b/src/Pckg/Framework/Environment.php @@ -7,9 +7,8 @@ use Pckg\Framework\Environment\Command\DefinePaths; use Pckg\Framework\Environment\Development; use Pckg\Framework\Environment\Production; -use Pckg\Manager\Asset\AssetManager; -class Environment implements AssetManager +class Environment { protected $urlPrefix = '/index.php'; @@ -26,6 +25,10 @@ class Environment implements AssetManager */ protected $config; + const EVENT_INITIALIZING = self::class . '.initializing'; + + const EVENT_INITIALIZED = self::class . '.initialized'; + public function __construct(Config $config, Context $context) { $this->config = $config; @@ -39,6 +42,11 @@ public function getUrlPrefix() return $this->urlPrefix; } + /** + * @param $url + * @return false|mixed|string + * @deprecated + */ public function replaceUrlPrefix($url) { if (strpos($url, $this->urlPrefix . '/') === 0) { @@ -50,11 +58,11 @@ public function replaceUrlPrefix($url) public function init() { - trigger(Environment::class . '.initializing', [$this]); + trigger(static::EVENT_INITIALIZING, [$this]); chain($this->initArray()); - trigger(Environment::class . '.initialized', [$this]); + trigger(static::EVENT_INITIALIZED, [$this]); return $this; } @@ -93,11 +101,6 @@ public function isUnix() { } - public function assets() - { - return []; - } - /** * @param Helper\Context $context * @param $appName diff --git a/src/Pckg/Framework/Environment/Console.php b/src/Pckg/Framework/Environment/Console.php index e5b947fc..eeabe816 100644 --- a/src/Pckg/Framework/Environment/Console.php +++ b/src/Pckg/Framework/Environment/Console.php @@ -4,6 +4,7 @@ use Pckg\Concept\Context; use Pckg\Framework\Environment; +use Pckg\Framework\Request\Data\Server; use Whoops\Handler\PlainTextHandler; use Whoops\Run; use Symfony\Component\Console\Application as SymfonyConsole; @@ -20,6 +21,7 @@ public function register() ini_set("display_errors", "1"); $this->config->parseDir(BASE_PATH); + $this->context->bind(Server::class, (new Server())->setFromGlobals()); $this->registerExceptionHandler(); @@ -42,7 +44,7 @@ public function createApplication(\Pckg\Framework\Helper\Context $context, $appN * - php console derive * - php console derive migrator:install */ - $argv = $_SERVER['argv']; + $argv = server('argv'); $commandIndex = null; foreach ($argv as $key => $arg) { if (strpos($arg, ':')) { diff --git a/src/Pckg/Framework/Environment/Development.php b/src/Pckg/Framework/Environment/Development.php index 7aa104e8..cb8cad2a 100644 --- a/src/Pckg/Framework/Environment/Development.php +++ b/src/Pckg/Framework/Environment/Development.php @@ -28,7 +28,7 @@ public function register() $this->config->parseDir(BASE_PATH); - if (false && isHttp() && !implicitDev()) { + if (isHttp() && !implicitDev()) { die('Unauthorized for dev!'); exit; } @@ -44,7 +44,7 @@ public function register() public function registerExceptionHandler() { $whoops = new Run(); - $whoops->pushHandler(function(\Throwable $e){ + $whoops->pushHandler(function (\Throwable $e) { @error_log(exception($e)); }); $whoops->pushHandler(new PrettyPageHandler()); diff --git a/src/Pckg/Framework/Environment/Production.php b/src/Pckg/Framework/Environment/Production.php index a7daf203..367e1f2e 100644 --- a/src/Pckg/Framework/Environment/Production.php +++ b/src/Pckg/Framework/Environment/Production.php @@ -104,11 +104,11 @@ protected function handleException(Throwable $e) /** * Handle JSON request. */ - if ($request->isJson() || $request->isAjax()) { + if ($request->isJson() || $request->isAjax() || $request->isCORS()) { $response = [ 'success' => false, 'error' => true, - 'message' => $e->getMessage(), + 'message' => $message, 'statusCode' => $response->getCode(), 'exception' => implicitDev() ? exception($e) : null, ]; @@ -165,9 +165,15 @@ protected function handleException(Throwable $e) public function getApplicationNameFromGlobalRouter() { $apps = config('router.apps', []); + $hostname = $_SERVER['HTTP_HOST'] ?? null; foreach ($apps as $app => $config) { - if (in_array($_SERVER['HTTP_HOST'], $config['host'])) { + if (isset($config['path'])) { + if (!in_array($_SERVER['SCRIPT_URL'], $config['path'])) { + continue; + } + } + if (in_array($hostname, $config['host'])) { return $app; } @@ -176,7 +182,7 @@ public function getApplicationNameFromGlobalRouter() } foreach ($config['host'] as $host) { - if (strpos($host, '(') !== false && preg_match('/' . $host . '/', $_SERVER['HTTP_HOST'])) { + if (strpos($host, '(') !== false && preg_match('/' . $host . '/', $hostname)) { return $app; } } diff --git a/src/Pckg/Framework/Command/Forked.php b/src/Pckg/Framework/Handler/Forked.php similarity index 93% rename from src/Pckg/Framework/Command/Forked.php rename to src/Pckg/Framework/Handler/Forked.php index 958b8b6b..63b73994 100644 --- a/src/Pckg/Framework/Command/Forked.php +++ b/src/Pckg/Framework/Handler/Forked.php @@ -1,6 +1,6 @@ get(Environment::class); } -} -/** - * @return mixed|string|array - */ -if (!function_exists('dotenv')) { + /** + * @return mixed|string|array + */ function dotenv($key, $default = null) { $dotenv = context()->getOrCreate(\josegonzalez\Dotenv\Loader::class, [], null, function () { @@ -61,19 +68,15 @@ function dotenv($key, $default = null) return $var[$key] ?? $default; } -} -/** - * @return Application - */ -if (!function_exists('app')) { + /** + * @return Application + */ function app() { return context()->get(Application::class); } -} -if (!function_exists('getDotted')) { function getDotted($data, $keys, $i = 0, $default = null) { if (!isset($keys[$i])) { @@ -84,9 +87,7 @@ function getDotted($data, $keys, $i = 0, $default = null) return $default; } -} -if (!function_exists('hasDotted')) { function hasDotted($data, $keys, $i = 0) { if (!isset($keys[$i])) { @@ -101,9 +102,7 @@ function hasDotted($data, $keys, $i = 0) return false; } -} -if (!function_exists('retry')) { function retry(callable $task, int $times = null, callable $onError = null, $interval = null) { $retry = new \Pckg\Framework\Helper\Retry(); @@ -122,9 +121,7 @@ function retry(callable $task, int $times = null, callable $onError = null, $int return $retry->make($task); } -} -if (!function_exists('request')) { /** * @return Request */ @@ -132,62 +129,50 @@ function request() { return context()->getOrCreate(Request::class); } -} -/** - * @return Post|mixed|string|null|array - */ -if (!function_exists('post')) { + /** + * @return Post|mixed|string|null|array + */ function post($key = null, $default = []) { return request()->post($key, $default); } -} -/** - * @return Request|mixed - */ -if (!function_exists('get')) { + /** + * @return Request|mixed + */ function get($key = null, $default = []) { return request()->get($key, $default); } -} -/** - * @return Request|mixed - */ -if (!function_exists('server')) { + /** + * @return Request|mixed + */ function server($key = null, $default = []) { return request()->server($key, $default); } -} -/** - * @return Request|mixed - */ -if (!function_exists('cookie')) { + /** + * @return Request|mixed + */ function cookie($key = null, $default = []) { return request()->cookie($key, $default); } -} -/** - * @return Request - */ -if (!function_exists('files')) { + /** + * @return Request + */ function files($key = null, $default = []) { return request()->files($key, $default); } -} -/** - * @return mixed - */ -if (!function_exists('required')) { + /** + * @return mixed + */ function required($value, $type = null, $key = null) { if (!$value) { @@ -204,9 +189,7 @@ function required($value, $type = null, $key = null) return $value; } -} -if (!function_exists('auth')) { /** * @return Auth */ @@ -220,9 +203,7 @@ function auth($provider = null) return $auth; } -} -if (!function_exists('uuid4')) { function uuid4($toString = true) { $uuid = \Ramsey\Uuid\Uuid::uuid4(); @@ -233,9 +214,7 @@ function uuid4($toString = true) return $uuid; } -} -if (!function_exists('response')) { /** * @return Response */ @@ -243,23 +222,17 @@ function response() { return context()->getOrCreate(Response::class); } -} -if (!function_exists('redirect')) { function redirect($url = null) { return response()->redirect($url); } -} -if (!function_exists('internal')) { function internal($url = null) { return response()->internal($url); } -} -if (!function_exists('entity')) { /** * @param null $entity * @@ -269,9 +242,7 @@ function entity($entity = null) { return context()->getEntity($entity); } -} -if (!function_exists('form')) { /** * @param null $form * @@ -281,9 +252,7 @@ function form($form = null) { return context()->getForm($form); } -} -if (!function_exists('factory')) { /** * @param $factory * @@ -293,9 +262,7 @@ function factory($factory) { return context()->getFactory($factory); } -} -if (!function_exists('schedule')) { /** * @param \Event $event * @param $strtotime @@ -304,9 +271,7 @@ function schedule(AbstractEvent $event, $strtotime) { // Event::schedule($event, $strtotime); } -} -if (!function_exists('isValidEmail')) { function isValidEmail($email, $dns = false) { if (!$email) { @@ -329,11 +294,9 @@ function isValidEmail($email, $dns = false) return true; } -} -/* router */ + /* router */ -if (!function_exists('router')) { /** * @return \Pckg\Framework\Router */ @@ -341,9 +304,7 @@ function router() { return context()->get(Router::class); } -} -if (!function_exists('url')) { /** * @param $url * @param array $params @@ -364,25 +325,19 @@ function url($url, $params = [], $absolute = false, $envPrefix = true) return exception($e); } } -} -if (!function_exists('email')) { function email($template, $receiver, $data = []) { $handler = config('pckg.mail.handler', QueueMailHandler::class); return Reflect::create($handler)->send($template, $receiver, $data); } -} -if (!function_exists('resolve')) { function resolve($class, $data = []) { return Reflect::resolve($class, $data); } -} -if (!function_exists('queue')) { /** * @return Queue */ @@ -395,14 +350,12 @@ function queue($channel = null, $command = null, $data = []) return $queue->queue($channel, $command, $data); } -} -if (!function_exists('chain')) { /** * @param $chains - * @param null $method + * @param null $method * @param array $args - * @param null $firstChain + * @param null $firstChain * * @return mixed|null|object * @throws Exception @@ -411,11 +364,9 @@ function chain($chains, $method = 'execute', array $args = [], callable $firstCh { return (new ChainOfResponsibility($chains, $method, $args, $firstChain))->runChains(); } -} -/* session */ + /* session */ -if (!function_exists('session')) { /** * @return mixed|Session */ @@ -429,9 +380,7 @@ function session($key = null, $default = null) return $session->get($key, $default); } -} -if (!function_exists('flash')) { /** * @param $key * @param null $val @@ -442,11 +391,9 @@ function flash($key, $val) { return context()->getOrCreate(Flash::class)->set($key, $val); } -} -/* config */ + /* config */ -if (!function_exists('config')) { /** * @param $text * @@ -462,9 +409,7 @@ function config($key = null, $default = null) return $config; } -} -if (!function_exists('first')) { function first(...$args) { foreach ($args as $arg) { @@ -475,9 +420,7 @@ function first(...$args) return null; } -} -if (!function_exists('oneFrom')) { function oneFrom($needle, $haystack, $default) { if (in_array($needle, $haystack)) { @@ -486,9 +429,7 @@ function oneFrom($needle, $haystack, $default) return $default; } -} -if (!function_exists('firstWithZero')) { function firstWithZero(...$args) { foreach ($args as $arg) { @@ -499,9 +440,7 @@ function firstWithZero(...$args) return null; } -} -if (!function_exists('path')) { /** * @param $key * @param null $val @@ -517,6 +456,10 @@ function path($key = null, $val = null) [$realKey] = explode('/', $key); $path = config('path.' . $realKey); + if (!$path) { + throw new Exception('Path ' . $key . ' is not defined'); + } + if (strpos($key, '/')) { $path .= rtrim(substr($key, strlen($realKey) + 1), '/') . '/'; } @@ -528,11 +471,13 @@ function path($key = null, $val = null) $path = str_replace(path('root'), path('ds'), $path); } + if ($key !== 'ds' && $val === '/') { + throw new Exception('Root path (/) is not allowed'); + } + return $path; } -} -if (!function_exists('relativePath')) { /** * @param $key * @param null $val @@ -543,9 +488,7 @@ function relativePath($key = null) { return str_replace(path('root'), '/', config('path.' . $key)); } -} -if (!function_exists('uniqueFile')) { /** * @param $filename * @param $dir @@ -563,11 +506,9 @@ function uniqueFile($filename, $folder) return $newPath; } -} -/* quick helpers */ + /* quick helpers */ -if (!function_exists('__i18n')) { function __i18n($key, $data = [], $lang = null) { try { @@ -592,16 +533,12 @@ function (Translator $translator) { throw $e; } } -} -if (!function_exists('__')) { function __($key, $data = [], $lang = null) { return __i18n($key, $data, $lang); } -} -if (!function_exists('toCamel')) { /** * @param $text * @@ -622,9 +559,7 @@ function toCamel($text) return ucfirst(str_replace("_", "", implode($text))); } -} -if (!function_exists('kaorealpath')) { /** * */ @@ -643,9 +578,7 @@ function kaorealpath($path) return implode('/', $new); } -} -if (!function_exists('view')) { /** * @param $view * @param array $data @@ -681,9 +614,7 @@ function view($view = null, $data = [], $assets = []) return $view; } -} -if (!function_exists('assetManager')) { /** * @return Asset */ @@ -691,9 +622,7 @@ function assetManager() { return context()->getOrCreate(Asset::class); } -} -if (!function_exists('vueManager')) { /** * @return Vue */ @@ -701,9 +630,7 @@ function vueManager() { return context()->getOrCreate(Vue::class); } -} -if (!function_exists('seoManager')) { /** * @return Seo */ @@ -711,9 +638,7 @@ function seoManager() { return context()->getOrCreate(Seo::class); } -} -if (!function_exists('localeManager')) { /** * @return Locale */ @@ -721,9 +646,7 @@ function localeManager() { return context()->getOrCreate(Locale::class); } -} -if (!function_exists('metaManager')) { /** * @return Meta */ @@ -731,9 +654,7 @@ function metaManager() { return context()->getOrCreate(Meta::class); } -} -if (!function_exists('gtmManager')) { /** * @return Gtm */ @@ -741,16 +662,12 @@ function gtmManager() { return context()->getOrCreate(Gtm::class); } -} -if (!function_exists('assets')) { function assets($assets) { assetManager()->addAssets($assets); } -} -if (!function_exists('autoloader')) { /** * @return mixed */ @@ -758,25 +675,19 @@ function autoloader() { return require BASE_PATH . "vendor/autoload.php"; } -} -if (!function_exists('isConsole')) { function isConsole() { return !request()->server('HTTP_HOST'); return !isset($_SERVER['HTTP_HOST']); } -} -if (!function_exists('isHttp')) { function isHttp() { return !!request()->server('HTTP_HOST'); return isset($_SERVER['HTTP_HOST']); } -} -if (!function_exists('dd')) { /** * @param mixed ...$mixed * @deprecated @@ -788,9 +699,7 @@ function dd(...$mixed) } die(); } -} -if (!function_exists('ddd')) { function ddd(...$mixed) { foreach ($mixed as $m) { @@ -798,9 +707,7 @@ function ddd(...$mixed) } die(); } -} -if (!function_exists('d')) { function d(...$mixed) { try { @@ -819,9 +726,7 @@ function d(...$mixed) return true; } -} -if (!function_exists('db')) { function db($depth = 3, $start = 0, $debug = true) { $db = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); @@ -836,23 +741,17 @@ function db($depth = 3, $start = 0, $debug = true) return $d; } -} -if (!function_exists('dev')) { function dev() { return env()->isDev(); } -} -if (!function_exists('prod')) { function prod() { return env()->isPro(); } -} -if (!function_exists('implicitDev')) { function implicitDev() { $remote = request()->clientIp(); @@ -876,23 +775,17 @@ function implicitDev() return false; } -} -if (!function_exists('win')) { function win() { return env()->isWin(); } -} -if (!function_exists('unix')) { function unix() { return env()->isUnix(); } -} -if (!function_exists('message')) { function message($message, $collector = 'messages') { if ($debugBar = debugBar()) { @@ -903,9 +796,7 @@ function message($message, $collector = 'messages') $debugBar->getCollector($collector)->addMessage($message); } } -} -if (!function_exists('array_merge_array')) { function array_merge_array($merge, $to) { foreach ($to as $key => &$val) { @@ -914,9 +805,7 @@ function array_merge_array($merge, $to) return $to; } -} -if (!function_exists('merge_arrays')) { function merge_arrays($to, $merge, $k = null) { $replace = config('pckg.config.parse.replace', []); @@ -965,9 +854,7 @@ function merge_arrays($to, $merge, $k = null) return $to; } -} -if (!function_exists('array_preg_match')) { function array_preg_match($patterns, $subject) { foreach ($patterns as $pattern) { @@ -978,9 +865,7 @@ function array_preg_match($patterns, $subject) return false; } -} -if (!function_exists('str_lreplace')) { function str_lreplace($search, $replace, $subject) { $pos = strrpos($subject, $search); @@ -991,9 +876,7 @@ function str_lreplace($search, $replace, $subject) return $subject; } -} -if (!function_exists('exception')) { /** * @param Exception $e * @@ -1004,9 +887,7 @@ function exception(Throwable $e, $parent = false) return $e->getMessage() . ' @ ' . $e->getFile() . ':' . $e->getLine() . ($parent && $e->getPrevious() ? ('(' . exception($e->getPrevious()) . ')') : ''); } -} -if (!function_exists('img')) { function img($name, $dir = null, $relative = true, $base = null) { if (!$name) { @@ -1025,16 +906,12 @@ function img($name, $dir = null, $relative = true, $base = null) ? str_replace(path('root'), path('ds'), $base) . $name : $base . $name; } -} -if (!function_exists('media')) { function media($name, $dir = null, $relative = true, $base = null) { return img($name, $dir, $relative, $base); } -} -if (!function_exists('runInLocale')) { function runInLocale($call, $locale) { $prevLocale = localeManager()->getCurrent(); @@ -1047,16 +924,12 @@ function runInLocale($call, $locale) return $response; } -} -if (!function_exists('isArrayList')) { function isArrayList($array) { return array_keys($array) === range(0, count($array) - 1); } -} -if (!function_exists('sluggify')) { function sluggify($str, $separator = '-', $special = null, $limit = 64) { /** @@ -1086,9 +959,7 @@ function sluggify($str, $separator = '-', $special = null, $limit = 64) return $str; } -} -if (!function_exists('get_date_diff')) { function get_date_diff($time1, $time2, $precision = 2) { // If not numeric then convert timestamps @@ -1142,9 +1013,7 @@ function get_date_diff($time1, $time2, $precision = 2) // Return string with times return implode(", ", $times); } -} -if (!function_exists('br2nl')) { function br2nl($string) { $string = str_replace(['
', '
', '
'], "\n", $string); @@ -1152,9 +1021,7 @@ function br2nl($string) return '"' . $string . '"'; } -} -if (!function_exists('array_union')) { function array_union($one, $two) { return array_merge( @@ -1163,21 +1030,17 @@ function array_union($one, $two) array_diff($two, $one) ); } -} -if (!function_exists('transform')) { function transform($collection, $rules) { return collect($collection)->map($rules)->all(); } -} -if (!function_exists('cache')) { /** - * @param null $key + * @param null $key * @param callable|null $value - * @param string $type - * @param int $time + * @param string $type + * @param int $time * * @return mixed|Cache|array|string * @throws Exception @@ -1190,9 +1053,7 @@ function cache($key = null, $value = null, $type = 'request', $time = 0) ? $cache->cache($key, $value, $type, $time) : $cache; } -} -if (!function_exists('between')) { function between($value, $min, $max) { $value = (int)$value; @@ -1204,74 +1065,80 @@ function between($value, $min, $max) return $value; } -} -if (!function_exists('route')) { function route($route = '', $view = 'index', $controller = null) { - return new Pckg\Framework\Router\Route\Route($route, $view, $controller); + return new Route($route, $view, $controller); } -} -if (!function_exists('vueRoute')) { /** * @param string $route * @param string|null $component * @param array $tags - * @return Router\Route\Route|Router\Route\VueRoute + * @param array $children + * @return Route|VueRoute */ function vueRoute(string $route = '', string $component = null, array $tags = [], array $children = []) { - return (new Router\Route\VueRoute($route, function () use ($tags) { - $config = config(); + $defaultTags = [ + 'vue:route', + ]; - $layout = null; - foreach ($tags as $tag) { - if (strpos($tag, 'layout:') === 0) { - $layout = 'Pckg/Generic:' . substr($tag, strlen('layout:')); - break; - } - } + /** + * Build the component. + */ + if ($component) { + $defaultTags['vue:route:template'] = substr($component, 0, 1) !== '<' + ? '<' . $component . '>' + : $component; + } - return view($layout ?? $config->get('pckg.router.layout', 'layout'), ['content' => Vue::getLayout()]); + // @phpstan-ignore-next-line + return (new VueRoute($route, function () use ($tags, $defaultTags) { + return $defaultTags['vue:route:template'] ?? Vue::getLayout(); }))->data([ - 'tags' => $tags ? array_merge($tags, [ - 'vue:route', - 'vue:route:template' => substr($component, 0, 1) !== '<' - ? '<' . $component . '>' - : $component, - ]) : [ - 'vue:route', - 'vue:route:template' => substr($component, 0, 1) !== '<' - ? '<' . $component . '>' - : $component, - ], - 'method' => 'GET', - ])->children($children); + 'tags' => $tags ? array_merge($defaultTags, $tags) : $defaultTags, + 'method' => 'GET', // what happens on other methods? + ])->children($children); } -} -if (!function_exists('routeGroup')) { - function routeGroup($data = [], $routes = []) + function routeGroup(array $data = [], array $routes = []) { - $routeGroup = new Pckg\Framework\Router\Route\Group($data); + return new Group($data, $routes); + } - if ($routes) { - $routeGroup->routes($routes); + function component($component, array $params = []) + { + $build = '<' . $component . ''; + $generic = null; + foreach ($params as $k => $v) { + if (substr($k, 0, 1) === ':') { + if (!$generic) { + // @phpstan-ignore-next-line + $generic = resolve(Generic::class); + } + + $store = true; + if (is_string($v) && substr($v, 0, 1) === '$') { + $key = '$store.state.generic.metadata.router[' . json_encode(substr($k, 1)) . ']'; + } else { + $key = $generic->pushMetadata('router', substr($k, 1), $v, $store); + } + $build .= ' ' . $k . '="' . $key . '"'; + } else { + $build .= ' ' . $k . '="' . $v . '"'; + } } + $build .= '>'; - return $routeGroup; + return $build; } -} -if (!function_exists('price')) { function price($price, $currency = null) { return number($price) . ' ' . ($currency ?? config('pckg.payment.currencySign')); } -} -if (!function_exists('number')) { function number($price) { if (is_null($price)) { @@ -1287,16 +1154,12 @@ function number($price) $localeManager->getThousandSeparator() ); } -} -if (!function_exists('is_associative_array')) { function is_associative_array($array) { return is_array($array) && (!$array || range(0, count($array) - 1) == array_keys($array)); } -} -if (!function_exists('strbetween')) { function strbetween($text, $from, $to) { $start = strpos($text, $from) + strlen($from); @@ -1304,9 +1167,7 @@ function strbetween($text, $from, $to) return substr($text, $start, $end - $start); } -} -if (!function_exists('cdn')) { function cdn($file) { $file = trim($file); @@ -1326,18 +1187,14 @@ function cdn($file) return 'https://' . $host . $file; } -} -if (!function_exists('isRemoteUrl')) { function isRemoteUrl($url) { $url = trim($url); return strpos($url, '//') === 0 || strpos($url, 'https://') === 0 || strpos($url, 'http://') === 0; } -} -if (!function_exists('only')) { function only($array, $keys, $keepUndefined = true) { $final = []; @@ -1354,16 +1211,12 @@ function only($array, $keys, $keepUndefined = true) return $final; } -} -if (!function_exists('onlyFromRequest')) { function onlyFromRequest(array $data, string $key = null) { return only($data, array_keys($key ? post($key) : post()->all()), false); } -} -if (!function_exists('onlyWhen')) { function onlyWhen($array, $keys) { if (!is_array($array) && !is_object($array)) { @@ -1388,25 +1241,19 @@ function onlyWhen($array, $keys) return $final; } -} -if (!function_exists('throwLogOrContinue')) { function throwLogOrContinue(Throwable $e) { if (dev() || isConsole()) { throw $e; } } -} -if (!function_exists('toSafeFilename')) { function toSafeFilename($filename, $special = ' ()\[\]#') { return substr(preg_replace("/[^A-Za-z0-9\-." . $special . "]/", '', $filename), -200); } -} -if (!function_exists('datetime')) { function datetime($date, $format = null) { if (!$format) { @@ -1415,9 +1262,7 @@ function datetime($date, $format = null) return (new Carbon($date))->format($format); } -} -if (!function_exists('datef')) { function datef($date, $format = null) { if (!$format) { @@ -1426,9 +1271,7 @@ function datef($date, $format = null) return (new Carbon($date))->format($format); } -} -if (!function_exists('timef')) { function timef($date, $format = null) { if (!$format) { @@ -1437,24 +1280,23 @@ function timef($date, $format = null) return (new Carbon($date))->format($format); } -} -if (!function_exists('sha1random')) { function sha1random() { - return sha1(\Defuse\Crypto\Key::createNewRandomKey()->saveToAsciiSafeString()); + return sha1(randomKey()); + } + + function randomKey() + { + return \Defuse\Crypto\Key::createNewRandomKey()->saveToAsciiSafeString(); } -} -if (!function_exists('filename')) { function filename($file) { $exploded = explode('/', $file); return end($exploded); } -} -if (!function_exists('escapeshellargs')) { function escapeshellargs($data) { $parameters = []; @@ -1490,9 +1332,7 @@ function escapeshellargs($data) return $parameters; } -} -if (!function_exists('seededShuffle')) { function seededShuffle($seed = null, $chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ') { $items = str_split($chars, 1); @@ -1504,9 +1344,7 @@ function seededShuffle($seed = null, $chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVW return implode($items); } -} -if (!function_exists('seededHash')) { function seededHash(int $seed, $length) { $shuffled = seededShuffle($seed); @@ -1521,9 +1359,7 @@ function seededHash(int $seed, $length) return implode($hash); } -} -if (!function_exists('str2int')) { function str2int($string, $max = PHP_INT_MAX) { $array = str_split($string, 1); @@ -1538,9 +1374,7 @@ function str2int($string, $max = PHP_INT_MAX) return (int)floor($range * $max); } -} -if (!function_exists('int2str')) { function int2str(int $int, $length = 8) { $chars = 'abcdefghijklmnopqrstuvwxyz'; @@ -1555,16 +1389,12 @@ function int2str(int $int, $length = 8) return str_pad($str, $length, 'a', STR_PAD_LEFT); } -} -if (!function_exists('numequals')) { function numequals($a, $b) { return abs((float)$a - (float)$b) < PHP_FLOAT_EPSILON; } -} -if (!function_exists('encryptBlob')) { function encryptBlob($plaintext, $password = null) { if (!$password) { @@ -1573,9 +1403,7 @@ function encryptBlob($plaintext, $password = null) return \Defuse\Crypto\Crypto::encryptWithPassword($plaintext, $password); } -} -if (!function_exists('decryptBlob')) { function decryptBlob($ciphertext, $password = null) { if (!$password) { @@ -1584,18 +1412,25 @@ function decryptBlob($ciphertext, $password = null) return \Defuse\Crypto\Crypto::decryptWithPassword($ciphertext, $password); } -} -if (!function_exists('appendIf')) { function appendIf($is, $append) { return $is ? $is . $append : ''; } -} -if (!function_exists('prependIf')) { function prependIf($prepend, $is) { return $is ? $prepend . $is : ''; } + + function forward($input, callable $task) + { + $task($input); + + return $input; + } + + function tryout() { + + } } diff --git a/src/Pckg/Framework/Helper/functions_bc.php b/src/Pckg/Framework/Helper/functions_bc.php new file mode 100644 index 00000000..053a7c47 --- /dev/null +++ b/src/Pckg/Framework/Helper/functions_bc.php @@ -0,0 +1,981 @@ + 'Pckg/Generic/View/error.twig', + ]); } catch (Throwable $e) { if (dev()) { throw $e; diff --git a/src/Pckg/Framework/Provider/Framework.php b/src/Pckg/Framework/Provider/Framework.php index d46b96fb..3d925c30 100644 --- a/src/Pckg/Framework/Provider/Framework.php +++ b/src/Pckg/Framework/Provider/Framework.php @@ -2,7 +2,7 @@ namespace Pckg\Framework\Provider; -use Pckg\Framework\Command\Forked; +use Pckg\Framework\Handler\Forked; use Pckg\Framework\Config; use Pckg\Framework\Console\Command\ClearCache; use Pckg\Framework\Console\Command\CreatePckgProject; @@ -26,12 +26,14 @@ class Framework extends Provider { + public function consoles() { return [ CreatePckgProject::class, ClearCache::class, ListRoutes::class, + Router\Console\MatchRoute::class, ]; } @@ -54,7 +56,7 @@ public function viewObjects() '_env' => Environment::class, //'_lang' => LangInterface::class, '_config' => Config::class, - '_session' => Session::class, // why is this commented out? + //'_session' => Session::class, // why is this commented out? '_cookie' => Cookie::class, // '_flash' => Flash::class, '_debugBar' => debugBar(), diff --git a/src/Pckg/Framework/Provider/Frontend.php b/src/Pckg/Framework/Provider/Frontend.php index e8bd1d4b..14c4aae1 100644 --- a/src/Pckg/Framework/Provider/Frontend.php +++ b/src/Pckg/Framework/Provider/Frontend.php @@ -12,7 +12,6 @@ public function assets() return [ 'libraries' => [ 'js/http.compiled.js', - 'js/pckg.compiled.js', ], ]; } diff --git a/src/Pckg/Framework/Provider/Helper/EntityResolver.php b/src/Pckg/Framework/Provider/Helper/EntityResolver.php index 5fb95eef..407859d0 100644 --- a/src/Pckg/Framework/Provider/Helper/EntityResolver.php +++ b/src/Pckg/Framework/Provider/Helper/EntityResolver.php @@ -25,7 +25,7 @@ public function by($field) public function getBy() { - return $this->by ?? 'id'; + return $this->by ?? ($this->e->getAliased() . '.id'); } public function parametrize($record) @@ -67,7 +67,7 @@ public function resolve($value) } if ($filter = $this->filter) { - $filter($this->e, $value); + $filter($this->e, $value, $this); } return $this->e->oneOrFail(); diff --git a/src/Pckg/Framework/Provider/Helper/PostValidationResolver.php b/src/Pckg/Framework/Provider/Helper/PostValidationResolver.php new file mode 100644 index 00000000..cd00c9cd --- /dev/null +++ b/src/Pckg/Framework/Provider/Helper/PostValidationResolver.php @@ -0,0 +1,25 @@ +validator = $validator; + + return $this; + } + + public function validate($resolved) + { + if ($this->validator) { + ($this->validator)($resolved); + } + + return $resolved; + } +} diff --git a/src/Pckg/Framework/Provider/Helper/Registrator.php b/src/Pckg/Framework/Provider/Helper/Registrator.php index 4c42b3f2..1429ea07 100644 --- a/src/Pckg/Framework/Provider/Helper/Registrator.php +++ b/src/Pckg/Framework/Provider/Helper/Registrator.php @@ -5,6 +5,7 @@ use Composer\Autoload\ClassLoader; use Pckg\Concept\Event\Dispatcher; use Pckg\Concept\Reflect; +use Pckg\Framework\Provider; use Pckg\Framework\Response; use Pckg\Framework\Stack; use Pckg\Framework\View\Twig; @@ -50,6 +51,7 @@ public function registerRoutes($routes) $arrProviders->register( [ 'provider' => get_class($this), + 'urlPrefix' => $this->routePrefix, ] ); continue; @@ -57,6 +59,7 @@ public function registerRoutes($routes) foreach ($arrProviders as $provider => $providerConfig) { if (isset($providerConfig['prefix'])) { + // why reset? $providerConfig['prefix'] = ''; } if (is_array($providerConfig)) { @@ -157,6 +160,11 @@ function () use ($app) { if ($stack->getStacks() && !config('app_parent')) { config()->set('app_parent', $stack->getStacks() ? $apps[0] : config('app', null)); } + + // reparse config + if ($apps) { + $stack->push(fn() => config()->parseDir(path('app'))); + } } /** @@ -235,6 +243,10 @@ public function registerListeners($handlers) public function registerJobs($jobs) { + if (!$jobs) { + return; + } + $jobManager = context()->getOrCreate(Job::class); foreach ($jobs as $job) { @@ -248,6 +260,10 @@ public function registerTranslations() return; } + if (!class_exists(Translator::class)) { + return; + } + $translatorService = context()->getOrCreate(Translator::class); $translatorService->addDir($this->getTranslationPath()); } diff --git a/src/Pckg/Framework/Provider/ResolvesMultiple.php b/src/Pckg/Framework/Provider/ResolvesMultiple.php new file mode 100644 index 00000000..835ea62b --- /dev/null +++ b/src/Pckg/Framework/Provider/ResolvesMultiple.php @@ -0,0 +1,8 @@ +bind($class, $newInstance); @@ -98,7 +98,7 @@ public function resolve($class) foreach (static::$parents as $parent) { if (in_array($parent, class_parents($class))) { - $newInstance = Reflect::create($class); + $newInstance = Reflect::create($class, $data); context()->bind($class, $newInstance); return $newInstance; @@ -109,7 +109,7 @@ public function resolve($class) if (interface_exists($class)) { foreach (static::$singletones as $s) { if (object_implements($s, $class)) { - $newInstance = Reflect::create($s); + $newInstance = Reflect::create($s, $data); context()->bind($class, $newInstance); return $newInstance; diff --git a/src/Pckg/Framework/Request.php b/src/Pckg/Framework/Request.php index cbd5b2fc..d1f4ed2c 100644 --- a/src/Pckg/Framework/Request.php +++ b/src/Pckg/Framework/Request.php @@ -5,6 +5,7 @@ use Pckg\Concept\Reflect; use Pckg\Framework\Helper\Lazy; use Pckg\Framework\Request\Data\Cookie; +use Pckg\Framework\Request\Data\Files; use Pckg\Framework\Request\Data\Get; use Pckg\Framework\Request\Data\Post; use Pckg\Framework\Request\Data\Server; @@ -39,10 +40,6 @@ class Request extends Message implements RequestInterface, ServerRequestInterfac const HEAD = 'HEAD'; - protected $router; - - protected $response; - protected $match; protected $internal = 0; @@ -58,14 +55,12 @@ class Request extends Message implements RequestInterface, ServerRequestInterfac public function __construct() { - Reflect::method($this, 'initDependencies'); - $this->server = (new Server())->setFromGlobals(); $this->request = (new DataRequest())->setFromGlobals(); $this->post = (new Post())->setFromGlobals(); $this->get = (new Get())->setFromGlobals(); $this->cookie = (new Cookie())->setFromGlobals(); - $this->files = (new Lazy($_FILES)); + $this->files = (new Files())->setFromGlobals(); $this->headers = collect(getallheaders())->groupBy(function ($value, $key) { return $key; })->all(); @@ -96,12 +91,6 @@ public function getHeaders() return $this->headers; } - public function initDependencies(Router $router, Response $response) - { - $this->router = $router; - $this->response = $response; - } - public function setInternal() { $this->internal++; @@ -388,7 +377,7 @@ public function isCORS() /** * Leave OPTIONS and GET? */ - return $this->isPost() || $this->isSearch() || $this->isDelete() || $this->isPut() || $this->isPatch() || $this->isHead(); + return !($this->isGet() || $this->isOptions()); } /** diff --git a/src/Pckg/Framework/Request/Command/InitRequest.php b/src/Pckg/Framework/Request/Command/InitRequest.php index bf22f258..36da43ba 100644 --- a/src/Pckg/Framework/Request/Command/InitRequest.php +++ b/src/Pckg/Framework/Request/Command/InitRequest.php @@ -4,11 +4,7 @@ use Pckg\Concept\AbstractChainOfReponsibility; use Pckg\Concept\Context; -use Pckg\Framework\Middleware\ShowNiceErrorPage; use Pckg\Framework\Request; -use Pckg\Framework\Router; -use Pckg\Framework\Router\Command\ResolveRoute; -use Pckg\Framework\View\Twig; class InitRequest extends AbstractChainOfReponsibility { @@ -17,79 +13,16 @@ class InitRequest extends AbstractChainOfReponsibility protected $context; - protected $router; - - public function __construct(Request $request, Context $context, Router $router) + public function __construct(Request $request, Context $context) { $this->request = $request; $this->context = $context; - $this->router = $router; } public function execute(callable $next) { $this->context->bind(Request::class, $this->request); - trigger(Request::class . '.initializing', [$this->request]); - - $url = $this->request->getUrl(); - - /** - * Check that router has any routes defined. - */ - if (!$this->router->getRoutes()) { - if ($this->request->isGet()) { - return response()->respond(view('vendor/pckg/framework/src/Pckg/Framework:default/new-project')); - } - return response()->respond(['success' => false, 'error' => true, 'message' => 'No routes']); - } - - $match = (new ResolveRoute($this->router, $url, first(server('HTTP_HOST'), config('domain'))))->execute(); - - if (!$match) { - /** - * Resolve without domain. - */ - message('Match by domain not found, matching without domain'); - $match = (new ResolveRoute($this->router, $url))->execute(); - } - - if (!$match) { - message('No route match found'); - response()->code(404); - trigger(ResolveRoute::class . '.notFound'); - - $match = [ - 'view' => function () { - if ($output = response()->getOutput()) { - return $output; - } - - if (request()->isJson() || request()->isAjax()) { - return (new ShowNiceErrorPage())->handleJson(['message' => 'Not found']); - } - - return (new ShowNiceErrorPage())->handlePartial(); - }, - 'tags' => ['layout:frontend'], - 'name' => null, - 'url' => null, - 'method' => 'GET', - 'resolvers' => [], - ]; - } - - $match = array_merge($match['data'] ?? [], $match); - - /** - * Do we need to set it in request and router? - */ - $this->router->setData($match); - $this->request->setMatch($match); - message('Match found ' . json_encode($match)); - - trigger(Request::class . '.initialized', [$this->request]); - return $next(); } } diff --git a/src/Pckg/Framework/Request/Command/InitRoute.php b/src/Pckg/Framework/Request/Command/InitRoute.php new file mode 100644 index 00000000..4522cdf0 --- /dev/null +++ b/src/Pckg/Framework/Request/Command/InitRoute.php @@ -0,0 +1,92 @@ +request = $request; + $this->router = $router; + } + + public function execute(callable $next) + { + trigger(Request::class . '.initializing', [$this->request]); + + $url = $this->request->getUrl(); + + /** + * Check that router has any routes defined. + */ + if (!$this->router->getRoutes()) { + if ($this->request->isGet()) { + return response()->respond(view('vendor/pckg/framework/src/Pckg/Framework:default/new-project')); + } + return response()->respond(['success' => false, 'error' => true, 'message' => 'No routes']); + } + + $match = (new ResolveRoute($this->router, $url, first(server('HTTP_HOST'), config('domain'))))->execute(); + + if (!$match) { + /** + * Resolve without domain. + */ + message('Match by domain not found, matching without domain'); + $match = (new ResolveRoute($this->router, $url))->execute(); + } + + if (!$match) { + message('No route match found'); + response()->code(404); + trigger(ResolveRoute::class . '.notFound'); + + $match = [ + 'view' => function () { + if ($output = response()->getOutput()) { + return $output; + } + + if (request()->isJson() || request()->isAjax()) { + return (new ShowNiceErrorPage())->handleJson(['message' => 'Not found']); + } + + return (new ShowNiceErrorPage())->handlePartial(); + }, + 'tags' => ['layout:frontend'], + 'name' => 'error', + 'url' => '/#error', + 'method' => 'GET', + 'resolvers' => [], + ]; + } + + $match = array_merge($match['data'] ?? [], $match); + + /** + * Do we need to set it in request and router? + */ + $this->router->setData($match); + $this->request->setMatch($match); + message('Match found ' . json_encode($match)); + + trigger(Request::class . '.initialized', [$this->request]); + + return $next(); + } +} diff --git a/src/Pckg/Framework/Request/Command/RunRequest.php b/src/Pckg/Framework/Request/Command/RunRequest.php index 8026753d..3f75cd50 100644 --- a/src/Pckg/Framework/Request/Command/RunRequest.php +++ b/src/Pckg/Framework/Request/Command/RunRequest.php @@ -21,7 +21,7 @@ public function execute(callable $next) { trigger(Request::class . '.running', [$this->request]); - Reflect::create(ProcessRouteMatch::class, ['match' => $this->request->getMatch()])->execute(); + Reflect::create(ProcessRouteMatch::class)->execute(); trigger(Request::class . '.ran', [$this->request]); diff --git a/src/Pckg/Framework/Request/Data/Cookie.php b/src/Pckg/Framework/Request/Data/Cookie.php index da14cb88..e0995535 100644 --- a/src/Pckg/Framework/Request/Data/Cookie.php +++ b/src/Pckg/Framework/Request/Data/Cookie.php @@ -45,6 +45,8 @@ public function set($name, $value = '', $expiration = self::DURATION_MONTH, $pat public function delete($name) { $this->set($name, null, -1 * static::EXPIRATION); + unset($this->data[$name]); + return $this; } } diff --git a/src/Pckg/Framework/Request/Data/Files.php b/src/Pckg/Framework/Request/Data/Files.php new file mode 100644 index 00000000..4f61672d --- /dev/null +++ b/src/Pckg/Framework/Request/Data/Files.php @@ -0,0 +1,16 @@ +setData($_FILES); + + return $this; + } +} diff --git a/src/Pckg/Framework/Request/Data/Session.php b/src/Pckg/Framework/Request/Data/Session.php index b7b60300..f8f505c0 100644 --- a/src/Pckg/Framework/Request/Data/Session.php +++ b/src/Pckg/Framework/Request/Data/Session.php @@ -53,4 +53,9 @@ public function __destruct() { // TODO: Implement __destruct() method. } + + public function getDriver() + { + return $this->driver; + } } diff --git a/src/Pckg/Framework/Request/Data/SessionDriver/Db.php b/src/Pckg/Framework/Request/Data/SessionDriver/Db.php index 919a744e..8769f710 100644 --- a/src/Pckg/Framework/Request/Data/SessionDriver/Db.php +++ b/src/Pckg/Framework/Request/Data/SessionDriver/Db.php @@ -46,4 +46,9 @@ public function gc($maxLifetime) { return true; } + + public function regenerate() + { + return $this; + } } diff --git a/src/Pckg/Framework/Request/Data/SessionDriver/FileDriver.php b/src/Pckg/Framework/Request/Data/SessionDriver/FileDriver.php index 08c91ef3..d319c154 100644 --- a/src/Pckg/Framework/Request/Data/SessionDriver/FileDriver.php +++ b/src/Pckg/Framework/Request/Data/SessionDriver/FileDriver.php @@ -84,8 +84,8 @@ public function register() $this->destroyCookieSession('Missing session signature! ' . $PHPSESSID); } else if (static::SECURE && !$PHPSESSIDSECURE && !auth()->hashedPasswordMatches($_SESSION[static::PHPSESSID . static::SIGNATURE], $PHPSESSID)) { /** - * Cookie defined session should have valid signature. - */ + * Cookie defined session should have valid signature. + */ $this->destroyCookieSession('Invalid session signature!'); } @@ -99,12 +99,15 @@ public function register() protected function startSession($SID = null, $PHPSESSID = null) { + $readAndClose = ($SID || $PHPSESSID) && (in_array('session:close', router()->get('tags')) || (!get('lang') && !post()->all()) || request()->isSearch()); + $readAndClose = false; + /** * Start a new session. */ $started = session_start([ 'cookie_lifetime' => static::DURATION, - 'read_and_close' => false, + 'read_and_close' => $readAndClose, ]); if (!$started) { @@ -140,7 +143,11 @@ protected function startSession($SID = null, $PHPSESSID = null) */ public function destroyCookieSession($message = null) { - session_destroy(); + try { + session_destroy(); + } catch (\Throwable $e) { + error_log(exception($e)); + } $_SESSION = []; $PHPSESSIDSECURE = $this->startSession(); //cookie()->set(static::PHPSESSID, null); @@ -151,4 +158,37 @@ public function destroyCookieSession($message = null) return $PHPSESSIDSECURE; } + + public function regenerate() + { + /** + * Deactivate current session. + */ + $_SESSION['deactivated'] = time(); + + /** + * Regenerate session and sign it. + */ + try { + //error_log('regenerating session ' . session_id()); + $regenerated = session_regenerate_id(true); + if (!$regenerated) { + error_log('Error regenerating session ' . session_id()); + } else { + //error_log('Session regenerated to ' . session_id()); + } + } catch (\Throwable $e) { + error_log('Cannot regenerate session, destroying session ' . session_id()); + session_start(); + $_SESSION = []; + //throw $e; + } + + /** + * Sign session and set it active. + */ + $sid = session_id(); + $_SESSION[FileDriver::PHPSESSID . FileDriver::SIGNATURE] = auth()->hashPassword($sid); + unset($_SESSION['deactivated']); + } } diff --git a/src/Pckg/Framework/Request/Data/SessionDriver/MockDriver.php b/src/Pckg/Framework/Request/Data/SessionDriver/MockDriver.php index 3c3ef3f7..d212413f 100644 --- a/src/Pckg/Framework/Request/Data/SessionDriver/MockDriver.php +++ b/src/Pckg/Framework/Request/Data/SessionDriver/MockDriver.php @@ -58,4 +58,9 @@ public function updateTimestamp($session_id, $session_data) { return $this; } + + public function regenerate() + { + return $this; + } } diff --git a/src/Pckg/Framework/Request/Message.php b/src/Pckg/Framework/Request/Message.php index 26c98556..1a1cb78f 100644 --- a/src/Pckg/Framework/Request/Message.php +++ b/src/Pckg/Framework/Request/Message.php @@ -7,6 +7,7 @@ use Pckg\Concept\Reflect; use Pckg\Framework\Helper\Lazy; use Pckg\Framework\Request\Data\Cookie; +use Pckg\Framework\Request\Data\Files; use Pckg\Framework\Request\Data\Get; use Pckg\Framework\Request\Data\Post; use Pckg\Framework\Request\Data\Server; @@ -53,7 +54,7 @@ public function __construct() $this->post = new Post(); $this->get = new Get(); $this->server = new Server(); - $this->files = new Lazy(); + $this->files = new Files(); $this->cookie = new Cookie(); $this->request = new \Pckg\Framework\Request\Data\Request(); diff --git a/src/Pckg/Framework/Response.php b/src/Pckg/Framework/Response.php index 1179e2fd..8ca2430f 100644 --- a/src/Pckg/Framework/Response.php +++ b/src/Pckg/Framework/Response.php @@ -2,12 +2,14 @@ namespace Pckg\Framework; +use Pckg\Collection; use Pckg\Framework\Request\Data\Flash; use Pckg\Framework\Request\Data\Session; use Pckg\Framework\Request\Message; use Pckg\Framework\Response\Command\RunResponse; use Pckg\Framework\Response\Exceptions; use Pckg\Framework\Router\URL; +use Pckg\Framework\View\ViewInterface; use Psr\Http\Message\ResponseInterface; use Throwable; @@ -145,6 +147,42 @@ public function getOutput() return $this->output; } + public function reparseOutput() + { + $this->output = $this->parseOutput(); + + return $this; + } + + public function parseOutput() + { + if (is_string($this->output) || is_array($this->output)) { + // print view as content + return $this->output; + } else if (is_object($this->output)) { + if ($this->output instanceof ViewInterface) { + // parse layout into view + return $this->output->autoparse(); + } else if ($this->output instanceof Collection) { + // convert to array + return $this->output->toArray(); + } else if (method_exists($this->output, '__toString')) { + return (string)$this->output; + } else if ($this->output instanceof \stdClass) { + return json_encode($this->output); + } else if ($this->output instanceof Response) { + $this->output = $this->output->getOutput(); + + return $this->parseOutput(); + } + } else if (is_null($this->output) || is_int($this->output) || is_bool($this->output)) { + // without view // no int? or bool? + return json_encode($this->output); + } + + throw new Exception("Output is unknown type " . (is_object($this->output) ? get_class($this->output) : '')); + } + private function getMinusUrl() { if (isset($_SERVER['HTTP_REFERER'])) { @@ -538,6 +576,26 @@ public function download($file, $filename, callable $then = null) $this->readFile($file, $then); } + public function downloadStream($stream, $filename, $length, $close = true, callable $then = null) + { + $this->sendFileContentTypeHeaders($filename); + $this->sendFileDispositionHeader($filename); + + if ($length) { + header('Content-Length: ' . $length); + } + + $limit = 1024 * 1024 * 10; + while (!feof($stream)) { + echo fread($stream, $limit); + flush(); + } + + $then && $then(); + fclose($stream); + exit; + } + public function printFile($file, $filename = null) { if (!$filename) { @@ -626,7 +684,7 @@ public function sendNoCacheHeaders() public function sendNoIndexHeader() { - header('X-Robots-Tax', 'noindex'); + header('X-Robots-Tag: noindex'); return $this; } diff --git a/src/Pckg/Framework/Response/Afterware/EncapsulateResponse.php b/src/Pckg/Framework/Response/Afterware/EncapsulateResponse.php index cbd02d68..032c9eb2 100644 --- a/src/Pckg/Framework/Response/Afterware/EncapsulateResponse.php +++ b/src/Pckg/Framework/Response/Afterware/EncapsulateResponse.php @@ -18,7 +18,11 @@ public function execute(callable $next) $router = router(); $tags = $router->get('tags'); - if (!in_array('layout:frontend', $tags)) { + /** + * Why only encapsulate frontend? + * Disabled. + */ + if (false && !in_array('layout:frontend', $tags)) { return $next(); } diff --git a/src/Pckg/Framework/Response/Command/ProcessRouteMatch.php b/src/Pckg/Framework/Response/Command/ProcessRouteMatch.php index 9637ebb9..fc59f0e3 100644 --- a/src/Pckg/Framework/Response/Command/ProcessRouteMatch.php +++ b/src/Pckg/Framework/Response/Command/ProcessRouteMatch.php @@ -9,6 +9,7 @@ use Pckg\Framework\Exception\Bad; use Pckg\Framework\Exception\NotFound; use Pckg\Framework\Exception\Unauthorized; +use Pckg\Framework\Request; use Pckg\Framework\Response; use Pckg\Framework\Response\Exception\TheEnd; use Pckg\Framework\Router\Command\ResolveDependencies; @@ -18,19 +19,17 @@ class ProcessRouteMatch extends AbstractChainOfReponsibility { - protected $match; - - protected $view; - protected $controller; + protected $request; + protected $response; protected $loadView; - public function __construct($match, Response $response, LoadView $loadView) + public function __construct(LoadView $loadView, Request $request, Response $response) { - $this->match = $match; + $this->request = $request; $this->response = $response; $this->loadView = $loadView; } @@ -39,6 +38,11 @@ public function execute() { $e = null; try { + /** + * Get defaults. + */ + $match = $this->request->getMatch(); + /** * Apply global middlewares. */ @@ -51,8 +55,8 @@ public function execute() /** * Apply route middlewares. */ - if (isset($this->match['middlewares'])) { - chain($this->match['middlewares'], 'execute'); + if (isset($match['middlewares'])) { + chain($match['middlewares'], 'execute'); } /** @@ -72,22 +76,24 @@ public function execute() $this->response->code(204)->respond(); }; - if (is_only_callable($this->match['view'])) { + + if (is_only_callable($match['view'])) { /** * Simple action will take all requests - GET, POST, DELETE, ... */ $processOptions(); - $response = Reflect::call($this->match['view'], $resolved); - } elseif (array_key_exists('controller', $this->match)) { + $response = Reflect::call($match['view'], $resolved); + $this->response->setOutput($response); + } elseif (array_key_exists('controller', $match)) { /** * Create controller object. */ - $this->controller = Reflect::create($this->match['controller']); + $this->controller = Reflect::create($match['controller']); /** * Check for OPTIONS. */ - $method = strtolower(request()->header('Access-Control-Request-Method')) . ucfirst($this->match['view']) . 'Action'; + $method = strtolower(request()->header('Access-Control-Request-Method')) . ucfirst($match['view']) . 'Action'; if (method_exists($this->controller, $method)) { $processOptions(); } elseif ($isOptionsRequest) { @@ -98,23 +104,26 @@ public function execute() * Get main action response. * This is where Resolvers may already Respond with final response. */ - $response = $this->loadView->set($this->match['view'], $resolved, $this->controller)->execute(); + $response = $this->loadView->set($match['view'], $resolved, $this->controller)->execute(); + if ($response !== $this->response) { + $this->response->setOutput($response); + } } else { /** * Vue route or similar? */ $processOptions(); - $response = $this->match['view']; + $response = $match['view']; + $this->response->setOutput($response); } /** * Trigger an event on successful response. + * Transform output to string or array. */ if (!$this->response->hasResponded()) { $dispatcher->trigger(ProcessRouteMatch::class . '.ran'); - $output = $this->parseView($response); - - $this->response->setOutput($output); + $this->response->reparseOutput(); } /** @@ -128,8 +137,8 @@ public function execute() /** * Apply route afterwares/decorators. */ - if (isset($this->match['afterwares'])) { - chain($this->match['afterwares'], 'execute', [$this->response]); + if (isset($match['afterwares'])) { + chain($match['afterwares'], 'execute', [$this->response]); } } catch (TheEnd $e) { /** @@ -185,31 +194,4 @@ public function execute() throw $e; } } - - public function parseView($viewData) - { - if (is_object($viewData)) { - if ($viewData instanceof ViewInterface) { - // parse layout into view - return $viewData->autoparse(); - } else if ($viewData instanceof Collection) { - // convert to array - return $viewData->toArray(); - } else if (method_exists($viewData, '__toString')) { - return (string)$viewData; - } else if ($viewData instanceof \stdClass) { - return json_encode($viewData); - } else if ($viewData instanceof Response) { - return $this->parseView($viewData->getOutput()); - } - } else if (is_string($viewData) || is_array($viewData)) { - // print view as content - return $viewData; - } else if (is_null($viewData) || is_int($viewData) || is_bool($viewData)) { - // without view - return null; - } - - throw new Exception("View is unknown type " . (is_object($viewData) ? get_class($viewData) : '')); - } } diff --git a/src/Pckg/Framework/Response/Command/RunResponse.php b/src/Pckg/Framework/Response/Command/RunResponse.php index 53791ea9..15ade4c1 100644 --- a/src/Pckg/Framework/Response/Command/RunResponse.php +++ b/src/Pckg/Framework/Response/Command/RunResponse.php @@ -6,6 +6,7 @@ use Pckg\Framework\Request; use Pckg\Framework\Response; use Pckg\Framework\View\AbstractView; +use Pckg\Generic\Service\Generic; class RunResponse extends AbstractChainOfReponsibility { @@ -36,11 +37,14 @@ public function execute(callable $next) $response->setOutput($response->arrayToString($output)); } else if (is_object($output) && method_exists($output, '__toString')) { $response->setOutput((string)$output); - } else if (is_string($output) && $isAjax && get('html')) { + } else if (is_string($output) && $isAjax) { $vue = vueManager()->getViews(); $response->setOutput($response->arrayToString([ 'html' => $output, 'vue' => $vue, + 'resolved' => router()->resolved(), + // @phpstan-ignore-next-line + 'metadata' => resolve(Generic::class)->getMetadata(), ])); } else if (is_bool($output)) { $response->setOutput($response->arrayToString(['success' => $output])); diff --git a/src/Pckg/Framework/Router.php b/src/Pckg/Framework/Router.php index f25731b7..03576678 100644 --- a/src/Pckg/Framework/Router.php +++ b/src/Pckg/Framework/Router.php @@ -268,7 +268,9 @@ public function make($routeName = null, $arguments = [], $absolute = false, $env * T00D00 - this needs to be resolved without proper index (find by class) */ if (isset($args['[' . $key . ']']) && is_object($args['[' . $key . ']'])) { - $realResolver = is_object($resolver) ? $resolver : resolve($resolver); + $realResolver = is_only_callable($resolver) ? $resolver() : (is_object($resolver) + ? $resolver + : resolve($resolver)); $recordObject = $args['[' . $key . ']']; $args['[' . $key . ']'] = $realResolver->parametrize($recordObject); /** @@ -414,13 +416,46 @@ protected function transformVueRoute($route, $prefix = '') $url = str_replace(['[', ']'], [':', ''], $url); $vueRoute = [ 'path' => $url, + 'name' => $route['name'], ]; if (array_key_exists('vue:route:redirect', $tags)) { $vueRoute['redirect'] = $prefix . $tags['vue:route:redirect']; } - if (array_key_exists('vue:route:template', $tags)) { - $vueRoute['component'] = ['template' => $tags['vue:route:template']]; + + /** + * When there's a layout, the layout should render the component. + */ + $component = null; + foreach ($tags as $k => $v) { + if (!is_string($v)) { + continue; + } + if ($k === 'layout') { + $component = '<' . $v . '>'; + } + if (strpos($v, 'layout:') === 0) { + if ($v === 'layout:frontend') { + //$component = ''; + } else if ($v === 'layout:backend') { + } else { // focused? blank? + $component = substr($v, strlen('layout:')); + $component = '<' . $component . '>'; + } + break; + } } + + /** + * VueJS. + */ + if ($component) { + $vueRoute['component'] = ['name' => sluggify($component), 'template' => $component]; + } else if (array_key_exists('vue:route:template', $tags)) { + $vueRoute['component'] = ['name' => sluggify($tags['vue:route:template']), 'template' => $tags['vue:route:template']]; + } else { + //$vueRoute['component'] = 'pb-router-layout'; + } + if (array_key_exists('vue:route:children', $tags)) { $routes = $this->getRoutes(); $vueRoute['children'] = []; @@ -438,7 +473,19 @@ protected function transformVueRoute($route, $prefix = '') $vueRoute['children'][] = $childRoute; } } - $vueRoute['meta']['tags'] = $tags; + + /** + * Frontend tags are objectized. ['vue:route', 't' => 'x'] becomes {'vue:route':true,'t':'x'} + */ + $finalTags = new \stdClass(); + foreach ($tags as $k => $v) { + if (is_numeric($k)) { + $finalTags->{$v} = true; + } else { + $finalTags->{$k} = $v; + } + } + $vueRoute['meta']['tags'] = $finalTags; /** * This needs to be available on the frontend so we can resolve the params on navigation. @@ -463,11 +510,17 @@ public function getVueRoutes() $firstRoute = $routeArr[0]; $tags = $firstRoute['tags'] ?? []; /** - * Skip non-vue routes. + * Skip non-vue routes, and non-vue child routes */ if (!in_array('vue:route', $tags)) { continue; } + /** + * Why skip child routes? + */ + if (false && in_array('vue:route:child', $tags)) { + continue; + } /** * Skip auth routes for non-auth users. */ diff --git a/src/Pckg/Framework/Router/Command/ResolveDependencies.php b/src/Pckg/Framework/Router/Command/ResolveDependencies.php index 8a423910..8ca944a9 100644 --- a/src/Pckg/Framework/Router/Command/ResolveDependencies.php +++ b/src/Pckg/Framework/Router/Command/ResolveDependencies.php @@ -2,6 +2,9 @@ namespace Pckg\Framework\Router\Command; +use Pckg\Concept\Resolver; +use Pckg\Framework\Provider\ResolvesMultiple; +use Pckg\Framework\Provider\RouteResolver; use Pckg\Framework\Router; class ResolveDependencies @@ -44,7 +47,12 @@ public function execute() } foreach ($resolvers as $urlKey => $resolver) { - if (is_object($resolver)) { + if (is_only_callable($resolver)) { + /** + * Callable was passed to optimize things. + */ + $realResolver = $resolver(); + } else if (is_object($resolver)) { /** * Resolver was passed. */ @@ -59,27 +67,28 @@ public function execute() /** * Create resolver. */ - $realResolver = resolve($resolver); + $realResolver = resolve($resolver, $data); } $k = $data[$urlKey] ?? null; - $resolved = $realResolver->resolve(urldecode($k)); + $resolved = is_object($realResolver) && \Pckg\Concept\Helper\object_implements($realResolver, RouteResolver::class) + ? $realResolver->resolve(urldecode($k)) + : $realResolver; + /** + * Validate resolved value for access? + */ + $resolvesMultiple = object_implements($realResolver, ResolvesMultiple::class); if (is_string($urlKey)) { $data[$urlKey] = $resolved; - } else { - $data[] = $resolved; - } - - if (!is_int($urlKey)) { router()->resolve($urlKey, $resolved); - /** - * Remove resolved key. - * Why? Can we delete it? - */ - if (isset($data[$urlKey])) { - //unset($data[$urlKey]); + } elseif ($resolvesMultiple) { + foreach ($resolved as $resolvedKey => $resolvedValue) { + $data[$resolvedKey] = $resolvedValue; + router()->resolve($resolvedKey, $resolvedValue); } + } else { + $data[] = $resolved; } } diff --git a/src/Pckg/Framework/Router/Command/ResolveRoute.php b/src/Pckg/Framework/Router/Command/ResolveRoute.php index 35007ed6..00862743 100644 --- a/src/Pckg/Framework/Router/Command/ResolveRoute.php +++ b/src/Pckg/Framework/Router/Command/ResolveRoute.php @@ -70,7 +70,6 @@ public function execute() $arrUrl = explode("/", substr($url, 1)); foreach ($routes as $routeArr) { foreach ($routeArr as $conf) { - // validate language if ($conf['language'] ?? false) { if ($this->domain) { @@ -83,8 +82,15 @@ public function execute() } // validate method - if (isset($conf['method']) && !empty($conf['method']) && !in_array(strtolower($_SERVER['REQUEST_METHOD']), explode("|", strtolower($conf['method'])))) { - continue; + $methods = $conf['method'] ?? null; + if ($methods && !is_array($methods)) { + $methods = explode('|', $methods); + } + if ($methods) { + $methods = collect($methods)->mapFn('strtolower')->all(); + if (!in_array(strtolower(server()->get('REQUEST_METHOD', '')), $methods)) { + continue; + } } $arrRoutes = explode("/", substr($conf["url"], 1)); diff --git a/src/Pckg/Framework/Router/Console/MatchRoute.php b/src/Pckg/Framework/Router/Console/MatchRoute.php new file mode 100644 index 00000000..5bc168a5 --- /dev/null +++ b/src/Pckg/Framework/Router/Console/MatchRoute.php @@ -0,0 +1,29 @@ +setName('router:match') + ->setDescription( + 'Match single route' + ) + ->addArgument('route'); + } + + public function handle() + { + $resolveRoute = resolve(ResolveRoute::class, ['url' => 'https://localhost' . $this->argument('route')])->execute(); + ddd($resolveRoute); + } +} diff --git a/src/Pckg/Framework/Router/Route/Group.php b/src/Pckg/Framework/Router/Route/Group.php index f07ccc41..ac52fc44 100644 --- a/src/Pckg/Framework/Router/Route/Group.php +++ b/src/Pckg/Framework/Router/Route/Group.php @@ -11,9 +11,10 @@ class Group protected $groups = []; - public function __construct($data = []) + public function __construct($data = [], array $routes = []) { $this->data = $data; + $this->routes = $routes; } public function routes($routes = []) @@ -36,6 +37,9 @@ public function register($parentData = []) * Merge parent data with current group data. */ $mergedData = array_merge($parentData, $this->data); + if (isset($parentData['urlPrefix']) && isset($this->data['urlPrefix'])) { + $mergedData['urlPrefix'] = $parentData['urlPrefix'] . $this->data['urlPrefix']; + } /** * Register groups. diff --git a/src/Pckg/Framework/Router/Route/Route.php b/src/Pckg/Framework/Router/Route/Route.php index eaf5d69e..8535a28b 100644 --- a/src/Pckg/Framework/Router/Route/Route.php +++ b/src/Pckg/Framework/Router/Route/Route.php @@ -110,6 +110,24 @@ public function resolvers($resolvers = []) return $this; } + public function getResolvers() + { + return $this->resolvers; + } + + public function inheritResolvers(Route $route) + { + foreach ($route->getResolvers() as $key => $resolver) { + if (isset($this->resolvers[$key])) { + continue; + } + + $this->resolvers[$key] = $resolver; + } + + return $this; + } + public function afterwares($afterwares = []) { $this->afterwares = $afterwares; diff --git a/src/Pckg/Framework/Router/Route/VueRoute.php b/src/Pckg/Framework/Router/Route/VueRoute.php index bc75f512..f36266dc 100644 --- a/src/Pckg/Framework/Router/Route/VueRoute.php +++ b/src/Pckg/Framework/Router/Route/VueRoute.php @@ -18,9 +18,15 @@ public function register($parentData) { $vueChildRoutes = []; if ($this->children) { - $vueChildRoutes = collect(array_keys($this->children))->map(function ($name) { - return $this->name . '.' . $name; - })->values(); + $vueChildRoutes = collect($this->children) + ->realReduce(function (VueRoute $vueRoute, $name, $reduce) { + $reduce[] = $this->name . '.' . trim($name, '.'); + $reduce = collect($vueRoute->children)->realReduce(function (VueRoute $vueRoute, $subname, $reduce) use ($name) { + $reduce[] = $this->name . '.' . trim($name, '.') . '.' . trim($subname, '.'); + return $reduce; + }, $reduce); + return $reduce; + }, []); $this->data['tags']['vue:route:children'] = $vueChildRoutes; } @@ -35,9 +41,19 @@ public function register($parentData) $childRoute->data['tags'][] = 'vue:route:child'; $parentData['urlPrefix'] = $url; $parentData['namePrefix'] = $name . '.' . $key; + $childRoute->inheritResolvers($this); $childRoute->register($parentData); } return [$url, $mergedData, $name]; } + + public function seo(array $array = []) + { + foreach ($array as $key => $val) { + $this->data['tags']['seo:' . $key] = $val; + } + + return $this; + } } diff --git a/src/Pckg/Framework/Test/Codeception/Cest.php b/src/Pckg/Framework/Test/Codeception/Cest.php new file mode 100644 index 00000000..1b4d7b0f --- /dev/null +++ b/src/Pckg/Framework/Test/Codeception/Cest.php @@ -0,0 +1,27 @@ +tester = $I; + + if (!isset($this->disableFramework)) { + $this->mockFramework(); + } + } +} diff --git a/src/Pckg/Framework/Test/ContextDiff.php b/src/Pckg/Framework/Test/ContextDiff.php new file mode 100644 index 00000000..3f3466dc --- /dev/null +++ b/src/Pckg/Framework/Test/ContextDiff.php @@ -0,0 +1,21 @@ +context->getData(); + $response = $task(); + $ending = $this->context->getData(); + $this->tester->assertEquals($diff, count($ending) - count($starting)); + + return $response; + } +} diff --git a/src/Pckg/Framework/Test/Helper.php b/src/Pckg/Framework/Test/Helper.php index b3509c79..4f8342b2 100644 --- a/src/Pckg/Framework/Test/Helper.php +++ b/src/Pckg/Framework/Test/Helper.php @@ -9,6 +9,11 @@ use Pckg\Database\Repository\PDO as PDORepository; use PDO; +/** + * Class Helper + * @package Pckg\Framework\Test + * @deprecated ? + */ class Helper extends Module { @@ -116,7 +121,7 @@ public function importDatabase($filename) } } - public function listenToQueries($type = null, $sort = true) + public function listenToQueries($type = null, $sort = false) { $this->sqls = []; diff --git a/src/Pckg/Framework/Test/ListenForEvents.php b/src/Pckg/Framework/Test/ListenForEvents.php new file mode 100644 index 00000000..2f99e85b --- /dev/null +++ b/src/Pckg/Framework/Test/ListenForEvents.php @@ -0,0 +1,55 @@ +listenForEvent($event, $reset); + } + + return $this; + } + + protected function listenForEvent(string $event, $reset = true): self + { + if ($reset) { + $this->triggeredEvents[$event] = 0; + } + + $this->context->get(Dispatcher::class)->listen($event, fn() => $this->triggeredEvents[$event]++); + + return $this; + } + + protected function getNumberOfTriggers(string $event): int + { + return $this->triggeredEvents[$event] ?? 0; + } + + protected function hasTriggered($events, int $min = 1): bool + { + if (!is_array($events)) { + $events = [$events]; + } + + foreach ($events as $event) { + if ($this->getNumberOfTriggers($event) < $min) { + return false; + } + } + + return true; + } +} diff --git a/src/Pckg/Framework/Test/MockConfig.php b/src/Pckg/Framework/Test/MockConfig.php new file mode 100644 index 00000000..c56cfef3 --- /dev/null +++ b/src/Pckg/Framework/Test/MockConfig.php @@ -0,0 +1,25 @@ +context->get(Config::class); + $reset = function () use ($original) { + $this->context->bind(Config::class, $original); + }; + $config = new Config($default); + + return $config; + } + + protected function getConfig(): Config + { + return $this->context->get(Config::class); + } +} diff --git a/src/Pckg/Framework/Test/MockContext.php b/src/Pckg/Framework/Test/MockContext.php new file mode 100644 index 00000000..b3643bb7 --- /dev/null +++ b/src/Pckg/Framework/Test/MockContext.php @@ -0,0 +1,44 @@ +getPckgBootstrap(); + + /** + * Only bootstrap and create context. Do not create environment or init the application. + * @var $context \Pckg\Concept\Context|\Pckg\Framework\Helper\Context + */ + $originalContext = context(); + Stack::$providers = []; + $this->context = $context = $bootstrap(null, null); + + $originalContext->bind(Context::class, $context); + $originalContext->bind(\Pckg\Framework\Helper\Context::class, $context); + + return $context; + } +} diff --git a/src/Pckg/Framework/Test/MockExceptions.php b/src/Pckg/Framework/Test/MockExceptions.php new file mode 100644 index 00000000..ee5c2f30 --- /dev/null +++ b/src/Pckg/Framework/Test/MockExceptions.php @@ -0,0 +1,17 @@ +tester->assertSame($message, $e->getMessage()); + } +} diff --git a/src/Pckg/Framework/Test/MockFramework.php b/src/Pckg/Framework/Test/MockFramework.php index 066f74c4..2ac8889d 100644 --- a/src/Pckg/Framework/Test/MockFramework.php +++ b/src/Pckg/Framework/Test/MockFramework.php @@ -13,6 +13,7 @@ trait MockFramework { + use MockContext; /** * @var \UnitTester @@ -20,40 +21,22 @@ trait MockFramework protected $tester; /** - * @var Context + * @var \Pckg\Framework\Helper\Context */ protected $context; - /** - * @return mixed - */ - protected function getPckgBootstrap() - { - $file = 'vendor/pckg/framework/src/bootstrap.php'; - if (!is_file($file)) { - $file = 'src/bootstrap.php'; - } - return include $file; - } + protected $recreateContext = true; - public function mockEnvironment() + protected function setRecreateContext($recreate = false) { - /** - * Make sure that App is fully loaded? - * We would like to mock the environment, application and request. - */ - $bootstrap = $this->getPckgBootstrap(); + $this->recreateContext = $recreate; - /** - * Only bootstrap and create context. Do not create environment or init the application. - * @var $context \Pckg\Concept\Context|\Pckg\Framework\Helper\Context - */ - $originalContext = context(); - Stack::$providers = []; - $this->context = $context = $bootstrap(null, null); + return $this; + } - $originalContext->bind(Context::class, $context); - $originalContext->bind(\Pckg\Framework\Helper\Context::class, $context); + protected function mockEnvironment() + { + $context = $this->mockContext(); /** * Create, bind and register the environment. @@ -77,9 +60,9 @@ public function mockEnvironment() return [$context, $config]; } - public function mockFramework($url = '/', $method = 'GET') + protected function mockFramework($url = '/', $method = 'GET') { - if (isset($this->context)) { + if (!$this->recreateContext && isset($this->context)) { $context = $this->context; $config = $context->get(Config::class); } else { @@ -131,13 +114,18 @@ protected function mergeRequestHeaders(Context $context, array $headers) return $this; } - public function mock() + protected function mock() { + // @phpstan-ignore-next-line return (new MockRequest($this, $this->app)); } - public function runExtensionDecorations(string $decoration) + protected function runExtensionDecorations($decoration) { + if (!is_string($decoration)) { + return; + } + foreach (get_class_methods($this) as $method) { if (strpos($method, $decoration) !== 0 || strpos($method, 'Extension') === false) { continue; diff --git a/src/Pckg/Framework/Test/MockInContext.php b/src/Pckg/Framework/Test/MockInContext.php new file mode 100644 index 00000000..f60144c7 --- /dev/null +++ b/src/Pckg/Framework/Test/MockInContext.php @@ -0,0 +1,14 @@ +context->bind($name ?? get_class($object), $object); + + return $object; + } +} diff --git a/src/Pckg/Framework/Test/MockRequest.php b/src/Pckg/Framework/Test/MockRequest.php index 38151c68..5faecc3c 100644 --- a/src/Pckg/Framework/Test/MockRequest.php +++ b/src/Pckg/Framework/Test/MockRequest.php @@ -53,7 +53,7 @@ class MockRequest * @param Unit $test * @param $app */ - public function __construct($test, $app) + protected function __construct($test, $app) { $this->test = $test; $this->app = $app; @@ -64,11 +64,11 @@ public function __construct($test, $app) * @throws \PHPUnit\Framework\ExpectationFailedException * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ - public function assertResponseCode($code) + protected function assertResponseCode($code, $message = null) { $response = $this->context->get(Response::class); - $this->test->assertEquals($code, $response->getCode(), 'Response code not ' . $code); + $this->test->assertEquals($code, $response->getCode(), $message ?? ('Response code not ' . $code)); return $this; } @@ -78,7 +78,7 @@ public function assertResponseCode($code) * @throws \PHPUnit\Framework\ExpectationFailedException * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ - public function assertResponseHas($key) + protected function assertResponseHas($key) { $responseObject = $this->context->get(Response::class); $response = $responseObject->getOutput(); @@ -94,11 +94,11 @@ public function assertResponseHas($key) * @throws \PHPUnit\Framework\ExpectationFailedException * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ - public function assertResponseContains($value) + protected function assertResponseContains($value) { $response = $this->context->get(Response::class)->getOutput(); - $this->test->assertEquals(true, strpos($response, $value) >= 0, 'Response does not contain ' . $value); + $this->test->assertEquals(true, str_contains($response, $value), 'Response does not contain ' . $value); return $this; } @@ -110,7 +110,7 @@ public function assertResponseContains($value) * @param null $mode * @return callable|\Closure|null */ - public function modifyConfigurator(callable $configurator = null, $mode = null) + protected function modifyConfigurator(callable $configurator = null, $mode = null) { if (!$mode && !$configurator) { return null; @@ -127,6 +127,7 @@ public function modifyConfigurator(callable $configurator = null, $mode = null) $request->server()->set('HTTP_X_PCKG_CSRF', metaManager()->getCsrfValue()); $request->server()->set('HTTP_REFERER', 'https://localhost'); $request->server()->set('HTTP_ORIGIN', 'localhost:99999'); + $request->server()->set('HTTP_HOST', 'localhost'); $this->mergeRequestHeaders($context, [ 'Accept' => 'application/json', 'X-Pckg-CSRF' => metaManager()->getCsrfValue(), @@ -142,7 +143,7 @@ public function modifyConfigurator(callable $configurator = null, $mode = null) * @param callable|null $configurator * @return $this */ - public function httpGet($url, callable $configurator = null, $mode = null) + protected function httpGet($url, callable $configurator = null, $mode = null) { return $this->fullHttpRequest($url, $this->modifyConfigurator($configurator, $mode), 'GET'); } @@ -152,7 +153,7 @@ public function httpGet($url, callable $configurator = null, $mode = null) * @param callable|null $configurator * @return $this */ - public function httpGetJson($url, callable $configurator = null) + protected function httpGetJson($url, callable $configurator = null) { return $this->fullHttpRequest($url, $this->modifyConfigurator($configurator, static::MODE_JSON), 'GET'); } @@ -162,7 +163,7 @@ public function httpGetJson($url, callable $configurator = null) * @param callable|null $configurator * @return $this */ - public function httpDelete($url, callable $configurator = null) + protected function httpDelete($url, callable $configurator = null) { return $this->fullHttpRequest($url, $this->modifyConfigurator($configurator), 'DELETE'); } @@ -173,7 +174,7 @@ public function httpDelete($url, callable $configurator = null) * @param callable|null $configurator * @return $this */ - public function httpPost($url, array $post = [], callable $configurator = null) + protected function httpPost($url, array $post = [], callable $configurator = null) { return $this->fullHttpRequest($url, function (Context $context) use ($post, $configurator) { $configurator = $this->modifyConfigurator($configurator, static::MODE_JSON); @@ -182,7 +183,7 @@ public function httpPost($url, array $post = [], callable $configurator = null) }, 'POST'); } - public function initApp($url = '/', callable $configurator = null, $method = 'GET') + protected function initApp($url = '/', callable $configurator = null, $method = 'GET') { $context = $this->mockFramework($url, $method); $environment = $context->get(Environment::class); @@ -213,11 +214,11 @@ public function initApp($url = '/', callable $configurator = null, $method = 'GE * @param callable|null $configurator * @param string $method */ - public function fullHttpRequest($url, callable $configurator = null, $method = 'GET') + protected function fullHttpRequest($url, callable $configurator = null, $method = 'GET') { $initialized = $this->initApp($url, $configurator, $method); if (!$initialized) { - throw new \Exception('Cannot initialize app ' . ($this->exception ? exception($e) : 'Unknown exception')); + throw new \Exception('Cannot initialize app ' . ($this->exception ? exception($this->exception) : 'Unknown exception')); } /** @@ -247,7 +248,7 @@ public function fullHttpRequest($url, callable $configurator = null, $method = ' /** * @return Context */ - public function getContext() + protected function getContext() { return $this->context; } @@ -256,7 +257,7 @@ public function getContext() * @return Response * @throws \Exception */ - public function getResponse() + protected function getResponse() { return $this->getContext()->get(Response::class); } @@ -265,7 +266,7 @@ public function getResponse() * @return mixed|string|array|null * @throws \Exception */ - public function getOutput() + protected function getOutput() { return $this->getResponse()->getOutput(); } @@ -274,7 +275,7 @@ public function getOutput() * @return mixed|string|array|null * @throws \Exception */ - public function getDecodedOutput() + protected function getDecodedOutput() { return json_decode($this->getOutput(), true); } diff --git a/src/Pckg/Framework/Test/MockRouter.php b/src/Pckg/Framework/Test/MockRouter.php new file mode 100644 index 00000000..f24cb70c --- /dev/null +++ b/src/Pckg/Framework/Test/MockRouter.php @@ -0,0 +1,43 @@ +context->get(Config::class)); + $this->context->bind(Router::class, $router); + + return $router; + } + + protected function fetchRouter(): Router + { + if ($this->context->exists(Router::class)) { + return $this->context->get(Router::class); + } + + return $this->mockRouter(); + } + + protected function registerRoutes(array $routes): Router + { + $router = $this->fetchRouter(); + + foreach ($routes as $url => $route) { + $router->add($url, $route); + } + + return $router; + } +} diff --git a/src/Pckg/Framework/Test/Queues.php b/src/Pckg/Framework/Test/Queues.php index 28b30377..5ab572e4 100644 --- a/src/Pckg/Framework/Test/Queues.php +++ b/src/Pckg/Framework/Test/Queues.php @@ -14,7 +14,5 @@ public function _beforeQueuesExtension() public function _afterQueuesExtension() { - } - } diff --git a/src/Pckg/Framework/Test/Transactions.php b/src/Pckg/Framework/Test/Transactions.php index c2a50645..a615e8e9 100644 --- a/src/Pckg/Framework/Test/Transactions.php +++ b/src/Pckg/Framework/Test/Transactions.php @@ -15,12 +15,12 @@ trait Transactions */ protected $mock; - public function startTransactions() + protected function startTransactions() { return $this; } - public function dropTransactions() + protected function dropTransactions() { return $this; } @@ -51,5 +51,4 @@ public function _afterTransactionsExtension() $repository->getConnection()->rollBack(); } } - } diff --git a/src/Pckg/Framework/View/Twig.php b/src/Pckg/Framework/View/Twig.php index 80b3edf2..402b3b0c 100644 --- a/src/Pckg/Framework/View/Twig.php +++ b/src/Pckg/Framework/View/Twig.php @@ -117,7 +117,11 @@ public function autoparse() trigger(View::class . '.loading', ['view' => $this->file, 'twig' => $this]); if ($this->file) { - $this->twig = $this->twig->loadTemplate($this->file . ".twig"); + if (strpos($this->file, '<') === false) { + $this->twig = $this->twig->loadTemplate($this->file . ".twig"); + } else { + $this->twig = $this->twig->createTemplate($this->file); + } } else { $this->twig = $this->twig->createTemplate($this->template); } diff --git a/src/Pckg/Framework/public/js/http.compiled.js b/src/Pckg/Framework/public/js/http.compiled.js index 5154429e..8dce1967 100644 --- a/src/Pckg/Framework/public/js/http.compiled.js +++ b/src/Pckg/Framework/public/js/http.compiled.js @@ -1,632 +1 @@ -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; -} : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; -}; - -var data = data || {}; -var http = { - - formToData: function formToData(vueElement, keys) { - var data = {}; - - if (typeof keys === 'undefined') { - $.each(vueElement.form, function (key, val) { - data[key] = val; - }); - } else { - $.each(keys, function (i, key) { - data[key] = vueElement.form[key]; - }); - } - - return data; - }, - - submitForm: function submitForm(vueElement, fields) { - return http.post($(vueElement.$el.attr('action')), http.formToData(vueElement, fields)); - }, - - ajax: function ajax(options, done, error) { - let presetBeforeSend = options.beforeSend || null; - options.beforeSend = function (request) { - if (presetBeforeSend) { - presetBeforeSend(request); - } - http.addLocale(request); - http.addCsrf(request); - }; - - options = Object.assign({ - dataType: 'JSON' - }, options || {}); - - let a = $.ajax(options); - - let preError = error || null; - error = function (response) { - /** - * Check for CSRF? - */ - if ($dispatcher && response.responseJSON && ['Cross Site Request Forbidden', 'Cross Site Request Invalid'].indexOf(response.responseJSON.message || '') >= 0) { - $dispatcher.$emit('notification:error', 'Your session has expired, please refresh your browser'); - } - - if (preError) { - preError(response); - } - }; - - if (a.done) { - if (done) { - a.done(done); - } - if (error) { - a.fail(error); - } - } else { - a.then(done || function(data){ console.log('no success handler', data); }, error || function(data){ console.log('no error handler', data); }); - } - - return a; - }, - - get: function (url, whenDone, whenError, options) { - return this.ajax(Object.assign({ - url: url, - type: 'GET' - }, options || {}), whenDone, whenError); - }, - - post: function post(url, data, whenDone, whenError) { - if (typeof data === 'function') { - data = data(); - } - - data = http.fixUndefined(data); - - return this.ajax({ - url: url, - type: 'POST', - data: data - }, whenDone, whenError); - }, - - patch: function post(url, data, whenDone, whenError) { - if (typeof data == 'function') { - data = data(); - } - - data = http.fixUndefined(data); - - return this.ajax({ - url: url, - type: 'PATCH', - data: data - }, whenDone, whenError); - }, - - put: function post(url, data, whenDone, whenError) { - if (typeof data == 'function') { - data = data(); - } - - data = http.fixUndefined(data); - - return this.ajax({ - url: url, - type: 'PATCH', - data: data - }, whenDone, whenError); - }, - - search: function get(url, whenDone, whenError, options) { - this.ajax(Object.assign({ - url: url, - type: 'SEARCH' - }, options || {}), whenDone, whenError); - }, - - delete: function (url, whenDone, whenError) { - return this.deleteJSON(url, whenDone, whenError); - }, - - deleteJSON: function deleteJSON(url, whenDone, whenError) { - return this.ajax({ - url: url, - type: 'DELETE' - }, whenDone, whenError); - }, - - getJSON: function getJSON(url, whenDone, whenError, options) { - return this.get(url, whenDone, whenError, options); - }, - - addCsrf: function(request) { - var elements = document.getElementsByName('pckgvdth'); - if (elements.length === 0) { - return; - } - request.setRequestHeader("X-Pckg-CSRF", elements[0].getAttribute('content')); - }, - - addLocale: function(request) { - if (!Pckg || !Pckg.config || !Pckg.config.locale || !Pckg.config.locale.current) { - return; - } - - request.setRequestHeader("X-Pckg-Locale", Pckg.config.locale.current); - }, - - form: function form($form, successCallback) { - return http.post($form.attr('action'), $form.serializeArray(), successCallback); - }, - - fixUndefined: function fixUndefined(data) { - if (typeof data === 'string' || typeof data === 'number') { - return data; - } else if (typeof data === 'undefined') { - return null; - } - - $.each(data, function (key, val) { - if (Array.isArray(val) || (typeof val === 'undefined' ? 'undefined' : _typeof(val)) == 'object') { - data[key] = http.fixUndefined(val); - } else if (typeof val == 'undefined') { - data[key] = ''; - } else if (val === true) { - data[key] = 1; - } else if (val === false || val === '' || val === null) { - data[key] = null; - } else { - data[key] = http.fixUndefined(val); - } - }); - - return data; - }, - - postDone: function postDone(json) { - if (typeof json.redirect !== 'undefined') { - if (typeof window.parent !== 'undefined' && window.parent.location.href.indexOf(json.redirect)) { - parent.postMessage('refresh', window.location.origin); - } else { - window.location.href = json.redirect; - } - } - }, - - postError: function postError(response) { - }, - - redirect: function redirect(url) { - if (!url || typeof url == 'undefined') { - url = window.location.href; - } - - window.location.href = url; - } - -}; - -var locale = { - - price: function price(_price, decimals, currency) { - return this.number(_price, decimals) + ' ' + (currency || Pckg.config.locale.currencySign); - }, - - number: function price(_price, decimals, locale) { - if (typeof decimals == 'undefined' || decimals === null) { - decimals = Pckg.config.locale.decimals; - } - - if (typeof _price == 'undefined' || _price === null) { - _price = 0.0; - } - - return parseFloat(_price).toLocaleString((locale || Pckg.config.locale.current).replace('_', '-').toLowerCase(), { - currency: 'eur', - currencyDisplay: 'symbol', - maximumFractionDigits: decimals, - minimumFractionDigits: decimals - }); - }, - - roundPrice: function roundPrice(price, decimals) { - if (typeof decimals == 'undefined' || decimals === null) { - decimals = Pckg.config.locale.decimals; - } - - if (typeof price == 'undefined' || price === null) { - price = 0.0; - } - - let digits = parseInt(price) == parseFloat(price) ? 0 : (decimals || 2); - - return parseFloat(price).toLocaleString(Pckg.config.locale.current.replace('_', '-').toLowerCase(), { - currency: 'eur', - currencyDisplay: 'symbol', - maximumFractionDigits: digits, - minimumFractionDigits: digits - }) + ' ' + Pckg.config.locale.currencySign; - }, - - roundNumber: function(number, decimals){ - if (typeof decimals == 'undefined' || decimals === null) { - decimals = Pckg.config.locale.decimals; - } - - if (typeof number == 'undefined' || number === null) { - number = 0.0; - } - - return parseInt(number) == parseFloat(number) ? parseInt(number) : parseFloat(number).toFixed(decimals || 2) - }, - - date: function date(_date) { - if (!_date) { - return null; - } - - moment.locale(Pckg.config.locale.current); - - return moment(_date).format(Pckg.config.locale.format.dateMoment); - }, - - time: function time(_time) { - if (!_time) { - return null; - } - - moment.locale(Pckg.config.locale.current); - - return moment(_time).format(Pckg.config.locale.format.timeMoment); - }, - - datetime: function datetime(_datetime) { - return this.date(_datetime) + ' ' + this.time(_datetime); - }, - - trans: function trans(_trans, params) { - $.each(params, function (key, val) { - _trans = _trans.replace('{{ ' + key + ' }}', val); - }); - - return _trans; - } - -}; - -var collection = { - - collect: function(items, of) { - return items.map((item) => { return new of(item) }); - }, - - groupBy: function (collection, groupBy) { - let groups = {}; - - $.each(collection, function (i, item) { - let group = groupBy(item, i); - if (!groups[group]) { - groups[group] = []; - } - groups[group].push(item); - }); - - return groups; - }, - - map: function (items, map) { - let mapped = {}; - - $.each(items, function (i, item) { - mapped[i] = collection.getCallableKey(map, item, i); - }); - - return mapped; - }, - - keyBy: function (items, key) { - let keyed = {}; - - $.each(items, function (i, item) { - keyed[collection.getCallableKey(key, item, i)] = item; - }); - - return keyed; - }, - - getCallableKey: function(key, item, i) { - if (typeof key === 'string') { - return item[key]; - } - - return key(item, i); - }, - - shuffle: function (unshuffled) { - return unshuffled - .map(function (a) { - return {sort: Math.random(), value: a}; - }) - .sort(function (a, b) { - return a.sort - b.sort; - }) - .map(function (a) { - return a.value; - }); - } - -}; - -var utils = { - - is: function (val) { - if (typeof val === 'number') { - return val.toString().length > 0; - } else if (typeof val === 'boolean') { - return val; - } else if (typeof val === 'string') { - return val.length > 0; - } - - return !!val; - }, - - lcfirst: function (str) { - if (!str) { - return ''; - } - - return str.charAt(0).toLowerCase() + str.slice(1); - }, - - ucfirst: function (str) { - if (!str) { - return ''; - } - - return str.charAt(0).toUpperCase() + str.slice(1); - }, - - toCamelCase: function(str) { - return str.replace(/^([A-Z])|\s(\w)/g, function(match, p1, p2, offset) { - if (p2) return p2.toUpperCase(); - return p1.toLowerCase(); - }); - }, - - isSameDate: function isSameDate(first, second) { - return locale.date(first) == locale.date(second); - }, - - fix: function fix(value) { - return value ? value : null; - }, - - url: function url(_url, params, absolute) { - if (!_url) { - return; - } - if (_url.indexOf('@') === 0 && Pckg.router.urls[_url.substring(1)]) { - _url = Pckg.router.urls[_url.substring(1)]; - } - if (_url.indexOf('@') === 0 && Pckg.router.urls[_url.substring(1) + ':' + Pckg.config.locale.current.substring(0, 2)]) { - _url = Pckg.router.urls[_url.substring(1) + ':' + Pckg.config.locale.current.substring(0, 2)]; - } - if (!_url) { - return; - } - $.each(params, function (key, val) { - _url = _url.replace('[' + key + ']', val); - }); - - if (_url.indexOf('@/') === 0) { - _url = _url.substring(1); - } - - if (absolute) { - _url = (Pckg.site.url || '') + _url; - } - - return _url; - }, - - sluggify: function (str) { - return str.replace(/[^a-zA-Z0-9 -]/g, '') - .replace(/[ -]+/g, '-') - .replace(/^-|-$/g, '') - .toLowerCase(); - }, - - nl2br: function nl2br(str, is_xhtml) { - var breakTag = is_xhtml || typeof is_xhtml === 'undefined' ? '
' : '
'; - return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2'); - }, - - html2text: function (html) { - let span = document.createElement('span'); - span.innerHTML = html; - return span.textContent || span.innerText; - }, - - closeIfIframe: function closeIfIframe() { - this.sendToParent('popup.close'); - }, - - closeAndRefresh: function closeAndRefresh() { - $.magnificPopup.close(); - http.redirect(); - }, - - sendToParent: function sendToParent(data) { - parent.postMessage(data, window.location.origin); - }, - - isIframe: function isIframe() { - return parent.window != window; - }, - - collect: function collect(item) { - return Array.isArray(item) ? item : [item]; - }, - prepend: function prepend(value, array) { - var newArray = array.slice(0); - - newArray.unshift(value); - - return newArray; - }, - sort: function sort(obj) { - var sorted = {}; - Object.keys(obj).sort().forEach(function (value, key) { - sorted[key] = value; - }); - - return sorted; - }, - mergeObject: function mergeObject(to, from) { - $.each(from, function (key, value) { - to[key] = value; - }); - - return to; - }, - pushTo: function pushTo(to, from) { - $.each(from, function (key, value) { - to.push(value); - }); - - return to; - }, - firstOf: function firstOf(items, callback) { - var first = null; - - $.each(items, function (i, item) { - if (callback(item, i)) { - first = item; - return false; - } - }); - - return first; - }, - lastOf: function lastOf(items, callback) { - return this.firstOf(items.reverse(), callback); - }, - last: function last(items) { - return items[items.length - 1]; - }, - next: function (all, current, noLoop) { - let i = all.indexOf(current) + 1; - if (i < 0) { - i = 0; - } else if (i >= all.length) { - if (noLoop) { - i = all.length - 1; - } else { - i = 0; - } - } - return all[i]; - }, - prev: function (all, current, noLoop) { - let i = all.indexOf(current) - 1; - if (i < 0) { - if (noLoop) { - i = 0; - } else { - i = all.length - 1; - } - } else if (i >= all.length) { - i = all.length - 1; - } - return all[i]; - }, - sortInt: function sortInt(a, b) { - return a < b ? -1 : a > b ? 1 : 0; - }, - splice: function splice(collection, item) { - let index = collection.indexOf(item); - if (index === -1) { - return collection; - } - return collection.splice(index, 1); - }, - toggle: function(items, key){ - if (items.indexOf(key) >= 0) { - utils.splice(items, key); - } else { - items.push(key); - } - }, - groupBy: function (collection, groupBy) { - grouped = {}; - $.each(collection, function (key, val) { - grouped[groupBy(val)] ? grouped[groupBy(val)].push(val) : (grouped[groupBy(val)] = [val]); - }); - - return grouped; - }, - - lazyTemplate: function (resolve, obj, url) { - if (typeof url !== 'string') { - url = url(obj); - } - http.getJSON(url, function (data) { - obj.template = data.template; - if (data.form) { - let originalData = obj.data; - obj.data = function () { - let d = originalData ? originalData.call(this) : {}; - d.form = data.form; - return d; - }; - } - resolve(obj); - }); - }, - - base64decode: function(str) { - return atob(str); - }, - - base64encode: function(str) { - return btoa(str); - } - -}; - -var settings = settings || {}; -settings.vue = settings.vue || {}; -settings.vue.gmaps = { - themes: { - getOptions: function getOptions(theme) { - var themes = settings.vue.gmaps.themes; - var options = themes.base; - - // merge with defaults - if (typeof themes[theme] != 'undefined') { - options = this.mergeOptions(options, themes[theme]); - } - - return options; - }, - mergeOptions: function mergeOptions(original, overwrite) { - $.each(overwrite, function (i, values) { - original[i] = values; - }); - - return original; - }, - base: { - zoom: 10, - center: [46.055144, 14.512284] - } - } -}; - -var d = function d(data) { - console.log(data); -}; +var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},data=data||{},http={ajax:function(e,t,n){let o=e.beforeSend||null;e.beforeSend=function(e){o&&o(e),http.addLocale(e),http.addCsrf(e)},e=Object.assign({dataType:"JSON"},e||{});let r=$.ajax(e),i=n||null;return n=function(e){$dispatcher&&e.responseJSON&&["Cross Site Request Forbidden","Cross Site Request Invalid"].indexOf(e.responseJSON.message||"")>=0&&$dispatcher.$emit("notification:error","Your session has expired, please refresh your browser"),i&&i(e)},r.done?(t&&r.done(t),n&&r.fail(n)):r.then(t||function(e){console.log("no success handler",e)},n||function(e){console.log("no error handler",e)}),r},get:function(e,t,n,o){return this.ajax(Object.assign({url:e,type:"GET"},o||{}),t,n)},post:function(e,t,n,o){return"function"==typeof t&&(t=t()),t=http.fixUndefined(t),this.ajax({url:e,type:"POST",data:t},n,o)},patch:function(e,t,n,o){return"function"==typeof t&&(t=t()),t=http.fixUndefined(t),this.ajax({url:e,type:"PATCH",data:t},n,o)},put:function(e,t,n,o){return"function"==typeof t&&(t=t()),t=http.fixUndefined(t),this.ajax({url:e,type:"PATCH",data:t},n,o)},search:function(e,t,n,o){this.ajax(Object.assign({url:e,type:"SEARCH"},o||{}),t,n)},delete:function(e,t,n){return this.deleteJSON(e,t,n)},deleteJSON:function(e,t,n){return this.ajax({url:e,type:"DELETE"},t,n)},getJSON:function(e,t,n,o){return this.get(e,t,n,o)},addCsrf:function(e){var t=document.getElementsByName("pckgvdth");0!==t.length&&e.setRequestHeader("X-Pckg-CSRF",t[0].getAttribute("content"))},addLocale:function(e){Pckg&&Pckg.config&&Pckg.config.locale&&Pckg.config.locale.current&&e.setRequestHeader("X-Pckg-Locale",Pckg.config.locale.current)},fixUndefined:function(e){return"string"==typeof e||"number"==typeof e?e:void 0===e?null:($.each(e,function(t,n){Array.isArray(n)||"object"==(void 0===n?"undefined":_typeof(n))?e[t]=http.fixUndefined(n):e[t]=void 0===n?"":!0===n?1:!1===n||""===n||null===n?null:http.fixUndefined(n)}),e)},postDone:function(e){void 0!==e.redirect&&(void 0!==window.parent&&window.parent.location.href.indexOf(e.redirect)?parent.postMessage("refresh",window.location.origin):window.location.href=e.redirect)},postError:function(e){},redirect:function(e){e&&void 0!==e||(e=window.location.href),window.location.href=e}},locale={price:function(e,t,n){return this.number(e,t)+" "+(n||Pckg.config.locale.currencySign)},number:function(e,t,n){return null==t&&(t=Pckg.config.locale.decimals),null==e&&(e=0),parseFloat(e).toLocaleString((n||Pckg.config.locale.current).replace("_","-").toLowerCase(),{currency:"eur",currencyDisplay:"symbol",maximumFractionDigits:t,minimumFractionDigits:t})},roundPrice:function(e,t){null==t&&(t=Pckg.config.locale.decimals),null==e&&(e=0);let n=parseInt(e)==parseFloat(e)?0:t||2;return parseFloat(e).toLocaleString(Pckg.config.locale.current.replace("_","-").toLowerCase(),{currency:"eur",currencyDisplay:"symbol",maximumFractionDigits:n,minimumFractionDigits:n})+" "+Pckg.config.locale.currencySign},roundNumber:function(e,t){return null==t&&(t=Pckg.config.locale.decimals),null==e&&(e=0),parseInt(e)==parseFloat(e)?parseInt(e):parseFloat(e).toFixed(t||2)},date:function(e){return e?(moment.locale(Pckg.config.locale.current),moment(e).format(Pckg.config.locale.format.dateMoment)):null},time:function(e){return e?(moment.locale(Pckg.config.locale.current),moment(e).format(Pckg.config.locale.format.timeMoment)):null},datetime:function(e){return this.date(e)+" "+this.time(e)}},collection={collect:function(e,t){return e.map(e=>new t(e))},groupBy:function(e,t){let n={};return $.each(e,function(e,o){let r=t(o,e);n[r]||(n[r]=[]),n[r].push(o)}),n},map:function(e,t){let n={};return $.each(e,function(e,o){n[e]=collection.getCallableKey(t,o,e)}),n},keyBy:function(e,t){let n={};return $.each(e,function(e,o){n[collection.getCallableKey(t,o,e)]=o}),n},getCallableKey:function(e,t,n){return"string"==typeof e?t[e]:e(t,n)}},utils={is:function(e){return"number"==typeof e?e.toString().length>0:"boolean"==typeof e?e:"string"==typeof e?e.length>0:!!e},lcfirst:function(e){return e?e.charAt(0).toLowerCase()+e.slice(1):""},ucfirst:function(e){return e?e.charAt(0).toUpperCase()+e.slice(1):""},url:function(e,t,n){if(e&&(0===e.indexOf("@")&&Pckg.router.urls[e.substring(1)]&&(e=Pckg.router.urls[e.substring(1)]),0===e.indexOf("@")&&Pckg.router.urls[e.substring(1)+":"+Pckg.config.locale.current.substring(0,2)]&&(e=Pckg.router.urls[e.substring(1)+":"+Pckg.config.locale.current.substring(0,2)]),e))return $.each(t,function(t,n){e=e.replace("["+t+"]",n)}),0===e.indexOf("@/")&&(e=e.substring(1)),n&&(e=(Pckg.site.url||"")+e),e},sluggify:function(e){return e.replace(/[^a-zA-Z0-9 -]/g,"").replace(/[ -]+/g,"-").replace(/^-|-$/g,"").toLowerCase()},nl2br:function(e,t){return(e+"").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g,"$1"+(t||void 0===t?"
":"
")+"$2")},html2text:function(e){let t=document.createElement("span");return t.innerHTML=e,t.textContent||t.innerText},isIframe:function(){return parent.window!=window},collect:function(e){return Array.isArray(e)?e:[e]},sort:function(e){var t={};return Object.keys(e).sort().forEach(function(e,n){t[n]=e}),t},next:function(e,t,n){let o=e.indexOf(t)+1;return o<0?o=0:o>=e.length&&(o=n?e.length-1:0),e[o]},prev:function(e,t,n){let o=e.indexOf(t)-1;return o<0?o=n?0:e.length-1:o>=e.length&&(o=e.length-1),e[o]},sortInt:function(e,t){return et?1:0},splice:function(e,t){let n=e.indexOf(t);return-1===n?e:e.splice(n,1)},toggle:function(e,t){e.indexOf(t)>=0?utils.splice(e,t):e.push(t)},groupBy:function(e,t){return grouped={},$.each(e,function(e,n){grouped[t(n)]?grouped[t(n)].push(n):grouped[t(n)]=[n]}),grouped},lazyTemplate:function(e,t,n){"string"!=typeof n&&(n=n(t)),http.getJSON(n,function(n){if(t.template=n.template,n.form){let e=t.data;t.data=function(){let t=e?e.call(this):{};return t.form=n.form,t}}e(t)})},base64decode:function(e){return atob(e)},base64encode:function(e){return btoa(e)}},settings=settings||{};settings.vue=settings.vue||{},settings.vue.gmaps={themes:{getOptions:function(e){var t=settings.vue.gmaps.themes,n=t.base;return void 0!==t[e]&&(n=this.mergeOptions(n,t[e])),n},mergeOptions:function(e,t){return $.each(t,function(t,n){e[t]=n}),e},base:{zoom:10,center:[46.055144,14.512284]}}};var d=function(e){console.log(e)};window.globalScrollTo=function(e,t){e.length<1||(t||(t=80),"parentIFrame"in window?parentIFrame.scrollToOffset(0,e.offset().top-t):(page=$("html,body"),page.on("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove",function(){page.stop()}),page.animate({scrollTop:e.offset().top-t},1e3,function(){page.off("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove")})))},window.observerOr=function(e,t){return"undefined"==typeof ResizeObserver?t():e()}; diff --git a/src/Pckg/Framework/public/js/http.js b/src/Pckg/Framework/public/js/http.js index 53a9bc86..b0ee9047 100644 --- a/src/Pckg/Framework/public/js/http.js +++ b/src/Pckg/Framework/public/js/http.js @@ -1,28 +1,6 @@ var data = data || {}; let http = window.http = { - formToData: function (vueElement, keys) { - var data = {}; - - if (typeof keys === 'undefined') { - $.each(vueElement.form, function (key, val) { - data[key] = val; - }); - - } else { - $.each(keys, function (i, key) { - data[key] = vueElement.form[key]; - }); - - } - - return data; - }, - - submitForm: function (vueElement, fields) { - return http.post($(vueElement.$el.attr('action')), http.formToData(vueElement, fields)); - }, - ajax: function ajax(options, done, error) { let presetBeforeSend = options.beforeSend || null; options.beforeSend = function (request) { @@ -154,10 +132,6 @@ let http = window.http = { request.setRequestHeader("X-Pckg-Locale", Pckg.config.locale.current); }, - form: function ($form, successCallback) { - return http.post($form.attr('action'), $form.serializeArray(), successCallback); - }, - fixUndefined: function (data) { if (typeof data === 'string' || typeof data === 'number') { return data; @@ -289,14 +263,6 @@ var locale = { return this.date(datetime) + ' ' + this.time(datetime); }, - trans: function (trans, params) { - $.each(params, function (key, val) { - trans = trans.replace('{{ ' + key + ' }}', val); - }); - - return trans; - } - }; var collection = { @@ -347,19 +313,6 @@ var collection = { return key(item, i); }, - shuffle: function (unshuffled) { - return unshuffled - .map(function (a) { - return {sort: Math.random(), value: a}; - }) - .sort(function (a, b) { - return a.sort - b.sort; - }) - .map(function (a) { - return a.value; - }); - } - }; var utils = { @@ -392,21 +345,6 @@ var utils = { return str.charAt(0).toUpperCase() + str.slice(1); }, - toCamelCase: function(str) { - return str.replace(/^([A-Z])|\s(\w)/g, function(match, p1, p2, offset) { - if (p2) return p2.toUpperCase(); - return p1.toLowerCase(); - }); - }, - - isSameDate: function (first, second) { - return locale.date(first) == locale.date(second); - }, - - fix: function (value) { - return value ? value : null; - }, - url: function (url, params, absolute) { if (!url) { return; @@ -453,19 +391,6 @@ var utils = { return span.textContent || span.innerText; }, - closeIfIframe: function () { - this.sendToParent('popup.close'); - }, - - closeAndRefresh: function () { - $.magnificPopup.close(); - http.redirect(); - }, - - sendToParent: function (data) { - parent.postMessage(data, window.location.origin); - }, - isIframe: function () { return parent.window != window; }, @@ -475,13 +400,6 @@ var utils = { ? item : [item]; }, - prepend: function (value, array) { - var newArray = array.slice(0); - - newArray.unshift(value); - - return newArray; - }, sort: function (obj) { var sorted = {}; Object.keys(obj).sort().forEach(function (value, key) { @@ -490,38 +408,6 @@ var utils = { return sorted; }, - mergeObject: function (to, from) { - $.each(from, function (key, value) { - to[key] = value; - }); - - return to; - }, - pushTo: function (to, from) { - $.each(from, function (key, value) { - to.push(value); - }); - - return to; - }, - firstOf: function (items, callback) { - var first = null; - - $.each(items, function (i, item) { - if (callback(item, i)) { - first = item; - return false; - } - }); - - return first; - }, - lastOf: function (items, callback) { - return this.firstOf(items.reverse(), callback); - }, - last: function (items) { - return items[items.length - 1]; - }, next: function (all, current, noLoop) { let i = all.indexOf(current) + 1; if (i < 0) { @@ -635,4 +521,39 @@ settings.vue.gmaps = { var d = function (data) { console.log(data); -}; \ No newline at end of file +}; + +//scroll to function, works on iframe, user can stop it by scrolling +window.globalScrollTo = function(target, offsetTop) +{ + if (target.length < 1) { + return; + } + + if (!offsetTop) { + offsetTop = 80; + } + + //scroll if iframe + if ('parentIFrame' in window) { + parentIFrame.scrollToOffset(0, target.offset().top - offsetTop); + //scroll if not iframe + } else { + page = $('html,body'); + + //stop scrolling if user interacts + page.on("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove", function () { + page.stop(); + }); + + page.animate({scrollTop: target.offset().top - offsetTop}, 1000, function () { + //stop scrolling if user interacts + page.off("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove"); + }); + } +} + +window.observerOr = function(observer, or) { + return typeof ResizeObserver === 'undefined' ? or() : observer(); +} + diff --git a/src/Pckg/Framework/public/js/pckg-generic-app-top.js b/src/Pckg/Framework/public/js/pckg-generic-app-top.js index 56f218e6..49070a73 100644 --- a/src/Pckg/Framework/public/js/pckg-generic-app-top.js +++ b/src/Pckg/Framework/public/js/pckg-generic-app-top.js @@ -1,7 +1,3 @@ -export const pckgDelimiters = { - delimiters: ['${', '}'] -}; - export const pckgSpannify = { methods: { spannify: function (text) { @@ -81,7 +77,7 @@ export const pckgTranslations = { let locale = Pckg.config.locale.current.toLowerCase(); translation = key[locale] || Object.values(key)[0]; } else { - translation = $store.state.translations[key] || key; + translation = typeof $store.state.translations[key] !== 'undefined' ? $store.state.translations[key] : key; if (false && Object.keys($store.state.translations).indexOf(key) === -1) { if ($store && $store.getters.isAdmin) { @@ -259,4 +255,4 @@ export const pckgNativeEvents = { $(element).off(callback); } } -}; \ No newline at end of file +}; diff --git a/src/Pckg/Framework/public/js/pckg.compiled.js b/src/Pckg/Framework/public/js/pckg.compiled.js deleted file mode 100644 index 6f4fa845..00000000 --- a/src/Pckg/Framework/public/js/pckg.compiled.js +++ /dev/null @@ -1,162 +0,0 @@ -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -var Pckg = Pckg || {}; -Pckg = Object.assign(Pckg, { - Collection: function (_Array) { - _inherits(Collection, _Array); - - function Collection() { - _classCallCheck(this, Collection); - - return _possibleConstructorReturn(this, (Collection.__proto__ || Object.getPrototypeOf(Collection)).apply(this, arguments)); - } - - _createClass(Collection, null, [{ - key: 'collect', - value: function collect(items, type) { - var collection = new Pckg.Collection(); - - $.each(items, function (i, item) { - collection.push(new type(item)); - }.bind(this)); - - return collection; - } - }]); - - return Collection; - }(Array), - Database: { - Record: function () { - function Record(data) { - _classCallCheck(this, Record); - - /** - * Set default relations. - */ - var relations = this.getEntity().getRelations(); - $.each(relations, function (key, setting) { - if ((typeof setting === 'undefined' ? 'undefined' : _typeof(setting)) == 'object') { - /** - * Relations type is defined by of (class) and/or type (Array/Object) - */ - if (setting.type == Array) { - /** - * Array relation - */ - data[key] = Pckg.Collection.collect(data[key] || [], setting.of); - } else { - /** - * Object relation - */ - data[key] = new setting.of(data[key] || {}); - } - } else { - data[key] = data[key] || new value(); - } - }); - - /** - * Set default fields. - */ - $.each(this.getEntity().getFields(), function (key, value) { - data[key] = data[key] || new value(); - }); - - /** - * Set default fields. - */ - $.each(this.getEntity().getCollections(), function (key, value) { - data[key] = value; - }); - - /** - * Bind data to object, set getters and setters for vue. - */ - $.each(data, function (key, val) { - this[key] = val; - }.bind(this)); - } - - _createClass(Record, [{ - key: '$set', - value: function $set(key, val) { - $vue.$set(this, key, val); - } - }, { - key: 'getData', - value: function getData() { - var _this2 = this; - - var fields = this.getEntity().getFields(); - var data = {}; - - $.each(fields, function (field, val) { - return data[field] = _this2[field] || val; - }); - - return data; - } - }, { - key: 'insert', - value: function insert(callback) { - var data = this.getData(); - - if (typeof callback == 'undefined') { - callback = function callback(data) { - }; - } - - http.post(this.getUrl('insert'), data, callback); - } - }, { - key: 'getEntity', - value: function getEntity() { - return new Pckg.Database.Entity(); - } - }]); - - return Record; - }(), - - Entity: function () { - function Entity() { - _classCallCheck(this, Entity); - } - - _createClass(Entity, [{ - key: 'getFields', - value: function getFields() { - return {}; - } - }, { - key: 'getRelations', - value: function getRelations() { - return {}; - } - }, { - key: 'getUrl', - value: function getUrl(type, data) { - if (type == 'insert') { - return utils.url(); - } - } - }, { - key: 'getCollections', - value: function getUrl() { - return {}; - } - }]); - - return Entity; - }() - } -}); diff --git a/src/Pckg/Framework/public/js/pckg.js b/src/Pckg/Framework/public/js/pckg.js deleted file mode 100644 index 3b511f23..00000000 --- a/src/Pckg/Framework/public/js/pckg.js +++ /dev/null @@ -1,118 +0,0 @@ -var Pckg = window.Pckg || {}; -Pckg = window.Pckg = Object.assign(Pckg, { - Collection: class extends Array { - - static collect(items, type) { - var collection = new Pckg.Collection(); - - $.each(items, function (i, item) { - collection.push(new type(item)); - }.bind(this)); - - return collection; - } - }, - Database: { - Record: class { - constructor(data) { - /** - * Set default relations. - */ - var relations = this.getEntity().getRelations(); - $.each(relations, function (key, setting) { - if (typeof setting == 'object') { - /** - * Relations type is defined by of (class) and/or type (Array/Object) - */ - if (setting.type == Array) { - /** - * Array relation - */ - data[key] = Pckg.Collection.collect(data[key] || [], setting.of); - } else { - /** - * Object relation - */ - data[key] = new setting.of(data[key] || {}); - } - } else { - data[key] = data[key] || new value; - } - }); - - /** - * Set default fields. - */ - $.each(this.getEntity().getFields(), function (key, value) { - data[key] = data[key] || new value; - }); - - /** - * Set default fields. - */ - $.each(this.getEntity().getCollections(), function (key, value) { - data[key] = value; - }); - - /** - * Bind data to object, set getters and setters for vue. - */ - $.each(data, function (key, val) { - this[key] = val; - }.bind(this)); - } - - $set(key, val) { - $vue.$set(this, key, val); - } - - getData() { - var fields = this.getEntity().getFields(); - var data = {}; - - $.each(fields, (field, val) => { - return data[field] = this[field] || val; - }); - - return data; - } - - insert(callback) { - var data = this.getData(); - - if (typeof callback == 'undefined') { - callback = function (data) { - } - } - - http.post(this.getUrl('insert'), data, callback); - } - - getEntity() { - return new Pckg.Database.Entity(); - } - }, - - Entity: class { - - getFields() { - return {}; - } - - getRelations() { - return {}; - } - - getUrl(type, data) { - if (type == 'insert') { - return utils.url() - } - } - - getCollections() { - return {}; - } - - } - } -}); \ No newline at end of file diff --git a/tests/_data/.gitkeep b/tests/_data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/_data/FrameworkConfigCommandInitConfigCest/config/defaults.php b/tests/_data/FrameworkConfigCommandInitConfigCest/config/defaults.php new file mode 100644 index 00000000..84e2a93d --- /dev/null +++ b/tests/_data/FrameworkConfigCommandInitConfigCest/config/defaults.php @@ -0,0 +1,5 @@ + 'barconfig', +]; diff --git a/tests/_support/_generated/AcceptanceTesterActions.php b/tests/_support/_generated/AcceptanceTesterActions.php index 90a2ba7d..fb2d6516 100644 --- a/tests/_support/_generated/AcceptanceTesterActions.php +++ b/tests/_support/_generated/AcceptanceTesterActions.php @@ -1,4 +1,4 @@ -getScenario()->runStep(new \Codeception\Step\Action('executeInGuzzle', func_get_args())); } @@ -126,7 +126,6 @@ public function executeInGuzzle($function) { * haveHttpHeader('X-Requested-With', 'Codeception'); * $I->amOnPage('test-headers.php'); - * ?> * ``` * * To use special chars in Header Key use HTML Character Entities: @@ -137,7 +136,6 @@ public function executeInGuzzle($function) { * ```php * haveHttpHeader('Client_Id', 'Codeception'); - * ?> * ``` * * @param string $name the name of the request header @@ -164,7 +162,6 @@ public function haveHttpHeader($name, $value) { * // ... * $I->deleteHeader('X-Requested-With'); * $I->amOnPage('some-other-page.php'); - * ?> * ``` * * @param string $name the name of the header to delete. @@ -696,7 +693,7 @@ public function dontSeeInField($field, $value) { * @param $params * @see \Codeception\Lib\InnerBrowser::seeInFormFields() */ - public function seeInFormFields($formSelector, $params) { + public function seeInFormFields($formSelector, array $params) { return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInFormFields', func_get_args())); } @@ -745,7 +742,7 @@ public function seeInFormFields($formSelector, $params) { * @param $params * @see \Codeception\Lib\InnerBrowser::dontSeeInFormFields() */ - public function dontSeeInFormFields($formSelector, $params) { + public function dontSeeInFormFields($formSelector, array $params) { return $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeInFormFields', func_get_args())); } @@ -924,7 +921,7 @@ public function dontSeeInFormFields($formSelector, $params) { * @param $button * @see \Codeception\Lib\InnerBrowser::submitForm() */ - public function submitForm($selector, $params, $button = NULL) { + public function submitForm($selector, array $params, $button = NULL) { return $this->getScenario()->runStep(new \Codeception\Step\Action('submitForm', func_get_args())); } @@ -937,7 +934,7 @@ public function submitForm($selector, $params, $button = NULL) { * ``` php * fillField("//input[@type='text']", "Hello World!"); - * $I->fillField(['name' => 'email'], 'jon@mail.com'); + * $I->fillField(['name' => 'email'], 'jon@example.com'); * ?> * ``` * @@ -1083,7 +1080,7 @@ public function sendAjaxGetRequest($uri, $params = []) { * 'task' => 'lorem ipsum', * 'category' => 'miscellaneous', * ]]); - * ``` + * ``` * * @param string $uri * @param array $params @@ -1107,7 +1104,7 @@ public function sendAjaxPostRequest($uri, $params = []) { * * @param $method * @param $uri - * @param $params + * @param array $params * @see \Codeception\Lib\InnerBrowser::sendAjaxRequest() */ public function sendAjaxRequest($method, $uri, $params = []) { @@ -1249,7 +1246,7 @@ public function grabValueFrom($field) { * @return mixed * @see \Codeception\Lib\InnerBrowser::setCookie() */ - public function setCookie($name, $val, $params = []) { + public function setCookie($name, $val, array $params = []) { return $this->getScenario()->runStep(new \Codeception\Step\Action('setCookie', func_get_args())); } @@ -1267,7 +1264,7 @@ public function setCookie($name, $val, $params = []) { * @return mixed * @see \Codeception\Lib\InnerBrowser::grabCookie() */ - public function grabCookie($cookie, $params = []) { + public function grabCookie($cookie, array $params = []) { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabCookie', func_get_args())); } @@ -1278,7 +1275,6 @@ public function grabCookie($cookie, $params = []) { * Grabs current page source code. * * @throws ModuleException if no page was opened. - * * @return string Current page source code. * @see \Codeception\Lib\InnerBrowser::grabPageSource() */ @@ -1304,7 +1300,7 @@ public function grabPageSource() { * @return mixed * @see \Codeception\Lib\InnerBrowser::seeCookie() */ - public function seeCookie($cookie, $params = []) { + public function seeCookie($cookie, array $params = []) { return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCookie', func_get_args())); } @@ -1321,7 +1317,7 @@ public function seeCookie($cookie, $params = []) { * @return mixed * @see \Codeception\Lib\InnerBrowser::dontSeeCookie() */ - public function dontSeeCookie($cookie, $params = []) { + public function dontSeeCookie($cookie, array $params = []) { return $this->getScenario()->runStep(new \Codeception\Step\Action('dontSeeCookie', func_get_args())); } @@ -1338,7 +1334,7 @@ public function dontSeeCookie($cookie, $params = []) { * @return mixed * @see \Codeception\Lib\InnerBrowser::resetCookie() */ - public function resetCookie($name, $params = []) { + public function resetCookie($cookie, array $params = []) { return $this->getScenario()->runStep(new \Codeception\Step\Action('resetCookie', func_get_args())); } @@ -1483,7 +1479,7 @@ public function seePageNotFound() { * $I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); * ``` * - * @param $code + * @param int $code * @see \Codeception\Lib\InnerBrowser::seeResponseCodeIs() */ public function seeResponseCodeIs($code) { @@ -1496,8 +1492,8 @@ public function seeResponseCodeIs($code) { * * Checks that response code is between a certain range. Between actually means [from <= CODE <= to] * - * @param $from - * @param $to + * @param int $from + * @param int $to * @see \Codeception\Lib\InnerBrowser::seeResponseCodeIsBetween() */ public function seeResponseCodeIsBetween($from, $to) { @@ -1517,7 +1513,7 @@ public function seeResponseCodeIsBetween($from, $to) { * // recommended \Codeception\Util\HttpCode * $I->dontSeeResponseCodeIs(\Codeception\Util\HttpCode::OK); * ``` - * @param $code + * @param int $code * @see \Codeception\Lib\InnerBrowser::dontSeeResponseCodeIs() */ public function dontSeeResponseCodeIs($code) { @@ -1651,10 +1647,9 @@ public function moveBack($numberOfSteps = 1) { * ```php * $I->setServerParameters([]); * ``` - * @param array $params * @see \Codeception\Lib\InnerBrowser::setServerParameters() */ - public function setServerParameters($params) { + public function setServerParameters(array $params) { return $this->getScenario()->runStep(new \Codeception\Step\Action('setServerParameters', func_get_args())); } @@ -1667,8 +1662,8 @@ public function setServerParameters($params) { * ```php * $I->haveServerParameter('name', 'value'); * ``` - * @param $name - * @param $value + * @param string $name + * @param string $value * @see \Codeception\Lib\InnerBrowser::haveServerParameter() */ public function haveServerParameter($name, $value) { diff --git a/tests/_support/_generated/FunctionalTesterActions.php b/tests/_support/_generated/FunctionalTesterActions.php index 4ba4a013..b69ca553 100644 --- a/tests/_support/_generated/FunctionalTesterActions.php +++ b/tests/_support/_generated/FunctionalTesterActions.php @@ -1,4 +1,4 @@ -mockFramework(); - } + use Cest; // tests public function defaultConfigTest(UnitTester $I) diff --git a/tests/unit/EntrypointCest.php b/tests/unit/EntrypointCest.php new file mode 100644 index 00000000..cfdd3d68 --- /dev/null +++ b/tests/unit/EntrypointCest.php @@ -0,0 +1,91 @@ +mockFramework(); + } + + // tests + public function bootstrapTest(UnitTester $I) + { + $included = require __ROOT__ . 'src/bootstrap.php'; + + $I->assertIsCallable($included); + + $context = $included(null, null); + $I->assertEquals(\Pckg\Framework\Helper\Context::class, get_class($context)); + + $context2 = $included(null, null); + $I->assertEquals(\Pckg\Framework\Helper\Context::class, get_class($context2)); + + $I->assertNotSame($context, $context2); + } + + public function productionTest(UnitTester $I) + { + if (isset($_SERVER['HTTP_HOST'])) { + unset($_SERVER['HTTP_HOST']); + } + $I->assertTrue(!isset($_SERVER['HTTP_HOST'])); + + try { + require __ROOT__ . 'src/production.php'; + throw new Exception('Exception not thrown'); + } catch (Throwable $e) { + $I->assertEquals('Class Test not found', $e->getMessage()); + } + + try { + $_SERVER['HTTP_HOST'] = 'test'; + require __ROOT__ . 'src/production.php'; + throw new Exception('Exception not thrown'); + } catch (Throwable $e) { + $I->assertEquals('Class Test not found', $e->getMessage()); + } + } + + public function developmentTest(UnitTester $I) + { + if (isset($_SERVER['HTTP_HOST'])) { + unset($_SERVER['HTTP_HOST']); + } + $I->assertTrue(!isset($_SERVER['HTTP_HOST'])); + + try { + require __ROOT__ . 'src/development.php'; + throw new Exception('Exception not thrown'); + } catch (Throwable $e) { + $I->assertEquals('Class Test not found', $e->getMessage()); + } + + try { + $_SERVER['HTTP_HOST'] = 'test'; + require __ROOT__ . 'src/development.php'; + throw new Exception('Exception not thrown'); + } catch (Throwable $e) { + $I->assertEquals('Class Test not found', $e->getMessage()); + } + } + + public function consoleTest(UnitTester $I) + { + $_SERVER['argv'] = [ + 'console', + 'test', + ]; + $_SERVER['argc'] = 2; + + try { + require __ROOT__ . 'src/console.php'; + throw new Exception('Exception not thrown'); + } catch (Throwable $e) { + $I->assertEquals('Class Test not found', $e->getMessage()); + } + } +} diff --git a/tests/unit/Framework/Application/Command/InitDatabaseCest.php b/tests/unit/Framework/Application/Command/InitDatabaseCest.php new file mode 100644 index 00000000..2118d049 --- /dev/null +++ b/tests/unit/Framework/Application/Command/InitDatabaseCest.php @@ -0,0 +1,68 @@ +checkContextDiff(function () { + $this->createInitDatabaseObject([])->execute(fn() => null); + }, 0); + } + + public function testEmptyDatabaseList(): void + { + $this->checkContextDiff(function () { + $this->createInitDatabaseObject([ + 'database' => [], + ])->execute(fn() => null); + }, 0); + } + + public function testSingleDatabaseRegistration(): void + { + $this->checkContextDiff(function () { + $this->createInitDatabaseObject([ + 'database' => [ + 'default' => [ + 'driver' => 'json', + 'db' => 'foo', + ], + ], + ])->execute(fn() => null); + }, 2); + } + + public function testDoubleDatabaseRegistration(): void + { + $this->checkContextDiff(function () { + $this->createInitDatabaseObject([ + 'database' => [ + 'default' => [ + 'driver' => 'json', + 'db' => 'foo', + ], + 'alternative' => [ + 'driver' => 'json', + 'db' => 'bar', + ], + ], + ])->execute(fn() => null); + }, 3); + } +} diff --git a/tests/unit/Framework/Application/Command/RegisterApplicationCest.php b/tests/unit/Framework/Application/Command/RegisterApplicationCest.php new file mode 100644 index 00000000..bbf89941 --- /dev/null +++ b/tests/unit/Framework/Application/Command/RegisterApplicationCest.php @@ -0,0 +1,38 @@ +mockConfig(); + + $localeManager = $this->mockInContext(new Pckg\Manager\Locale(new \Pckg\Locale\Lang())); + + $this->listenForEvent(\Pckg\Framework\Application::EVENT_REGISTERED); + + $registerApplication = new \Pckg\Framework\Application\Command\RegisterApplication($application, $config); + $registerApplication->execute(fn() => null); + + $this->tester->assertTrue($provider->isRegistered()); + $this->tester->assertEquals([], $config->get()); + $this->tester->assertEquals('en_GB', $localeManager->getCurrent()); + $this->tester->assertEquals(1, $this->getNumberOfTriggers(\Pckg\Framework\Application::EVENT_REGISTERED)); + } +} diff --git a/tests/unit/Framework/Application/Console/Command/RunCommandCest.php b/tests/unit/Framework/Application/Console/Command/RunCommandCest.php new file mode 100644 index 00000000..fa177296 --- /dev/null +++ b/tests/unit/Framework/Application/Console/Command/RunCommandCest.php @@ -0,0 +1,55 @@ +mockInContext(new NullOutput(), RunCommand::class . '.output'); + $dispatcher = $this->mockInContext(new Dispatcher()); + + $this->listenForEvent(RunCommand::EVENT_RUNNING); + $this->listenForEvent(static::EVENT_MIDDLEWARE); + $this->listenForEvent(static::EVENT_AFTERWARE); + + $response = new Response(); + $response->addMiddleware(function () { + dispatcher()->trigger(static::EVENT_MIDDLEWARE); + }); + $response->addAfterware(function () { + dispatcher()->trigger(static::EVENT_AFTERWARE); + }); + + $symfonyConsole = new Application(); + $symfonyConsole->setAutoExit(false); + $server = new Server(); + + (new RunCommand($response, $dispatcher, $symfonyConsole, $server))->execute(fn() => null); + + $this->tester->assertEquals(1, $this->getNumberOfTriggers(RunCommand::EVENT_RUNNING)); + $this->tester->assertEquals(1, $this->getNumberOfTriggers(static::EVENT_MIDDLEWARE)); + $this->tester->assertEquals(1, $this->getNumberOfTriggers(static::EVENT_AFTERWARE)); + } +} diff --git a/tests/unit/Framework/Application/ConsoleCest.php b/tests/unit/Framework/Application/ConsoleCest.php new file mode 100644 index 00000000..e78076c7 --- /dev/null +++ b/tests/unit/Framework/Application/ConsoleCest.php @@ -0,0 +1,30 @@ +tester->assertNotEmpty($console->inits()); + $this->tester->assertNotEmpty($console->runs()); + } +} diff --git a/tests/unit/Framework/Application/QueueCest.php b/tests/unit/Framework/Application/QueueCest.php new file mode 100644 index 00000000..fa66dfc1 --- /dev/null +++ b/tests/unit/Framework/Application/QueueCest.php @@ -0,0 +1,30 @@ +tester->assertNotEmpty($queue->inits()); + $this->tester->assertNotEmpty($queue->runs()); + } +} diff --git a/tests/unit/Framework/Application/WebsiteCest.php b/tests/unit/Framework/Application/WebsiteCest.php new file mode 100644 index 00000000..ca851290 --- /dev/null +++ b/tests/unit/Framework/Application/WebsiteCest.php @@ -0,0 +1,30 @@ +tester->assertNotEmpty($website->inits()); + $this->tester->assertNotEmpty($website->runs()); + } +} diff --git a/tests/unit/Framework/Config/Command/InitConfigCest.php b/tests/unit/Framework/Config/Command/InitConfigCest.php new file mode 100644 index 00000000..e32247bf --- /dev/null +++ b/tests/unit/Framework/Config/Command/InitConfigCest.php @@ -0,0 +1,30 @@ +mockConfig(); + $initial = $config->get(); + path('app', __ROOT__ . 'tests/_data/FrameworkConfigCommandInitConfigCest/'); + (new InitConfig($config))->execute(fn() => null); + $final = $config->get(); + $this->tester->assertNotSame($initial, $final); + $this->tester->assertSame(['foo' => 'barconfig', 'url' => 'https://'], $final); + } +} diff --git a/tests/unit/Framework/Environment/Command/DefinePathsCest.php b/tests/unit/Framework/Environment/Command/DefinePathsCest.php new file mode 100644 index 00000000..db5e710e --- /dev/null +++ b/tests/unit/Framework/Environment/Command/DefinePathsCest.php @@ -0,0 +1,50 @@ + '/', + 'root' => $path, + 'apps' => $path . 'app/', + 'src' => $path . 'src/', + 'storage' => $path . 'storage/', + 'private' => $path . 'storage/private/', + 'public' => $path . 'storage/public/', + 'www' => $path . 'www/', + 'cache' => $path . 'storage/cache/', + 'tmp' => $path . 'storage/tmp/', + 'uploads' => $path . 'storage/uploads/', + 'vendor' => $path . 'vendor/', + 'build' => $path . 'build/', + ]; + + $preRegistered = true; + if (!$preRegistered) { + foreach ($paths as $key => $val) { + try { + path($key); + throw new \Exception('Miss-exception ' . $key); + } catch (\Throwable $e) { + $this->tester->assertNotEquals('Miss-exception ' . $key, $e->getMessage()); + } + } + + (new DefinePaths())->execute(fn() => null); + } + + foreach ($paths as $key => $val) { + $this->tester->assertEquals($val, path($key), 'Checking ' . $key); + } + } +} diff --git a/tests/unit/Framework/Environment/ConsoleCest.php b/tests/unit/Framework/Environment/ConsoleCest.php new file mode 100644 index 00000000..a38a107a --- /dev/null +++ b/tests/unit/Framework/Environment/ConsoleCest.php @@ -0,0 +1,49 @@ +mockConfig(); + + $this->tester->assertFalse($config->hasRegisteredDir(BASE_PATH)); + + $this->listenForEvents([Environment::EVENT_INITIALIZING, Environment::EVENT_INITIALIZED]); + + // this is being tested + (new Console($config, $this->context))->register(); + + $this->tester->assertEquals(E_ALL, error_reporting()); + $this->tester->assertEquals('1', ini_get('display_errors')); + + $this->tester->assertTrue($config->hasRegisteredDir(BASE_PATH)); + + $this->tester->assertEquals(1, $this->getNumberOfTriggers(Environment::EVENT_INITIALIZING)); + $this->tester->assertEquals(1, $this->getNumberOfTriggers(Environment::EVENT_INITIALIZED)); + } + + public function testConsoleAppCreation() + { + $config = $this->context->get(Config::class); + + try { + (new Console($config, $this->context))->createApplication($this->context, 'test'); + throw new \Exception('Miss-exception'); + } catch (\Throwable $e) { + $this->tester->assertEquals('Class Test not found', $e->getMessage()); + } + } +} diff --git a/tests/unit/Framework/EnvironmentCest.php b/tests/unit/Framework/EnvironmentCest.php new file mode 100644 index 00000000..cdaa78c7 --- /dev/null +++ b/tests/unit/Framework/EnvironmentCest.php @@ -0,0 +1,39 @@ +mockContext(); + $config = new Config(); + + $I->assertFalse($context->exists(Config::class)); + + $environment = new Environment($config, $context); + + $I->assertTrue($context->exists(Config::class)); + + $I->assertEquals('/index.php', $environment->getUrlPrefix()); + $I->assertNotEmpty($environment->initArray()); + + $this->listenForEvents([Environment::EVENT_INITIALIZING, Environment::EVENT_INITIALIZED]); + + $environment->init(); + + $I->assertTrue($this->hasTriggered([Environment::EVENT_INITIALIZING, Environment::EVENT_INITIALIZED])); + } +} diff --git a/tests/unit/Framework/Reflect/FrameworkResolverCest.php b/tests/unit/Framework/Reflect/FrameworkResolverCest.php new file mode 100644 index 00000000..d2a0b91c --- /dev/null +++ b/tests/unit/Framework/Reflect/FrameworkResolverCest.php @@ -0,0 +1,72 @@ +createFrameworkResolver(); + $this->tester->assertFalse($frameworkResolver->canResolve(static::class), static::class); + } + + public function testCantResolveNonExistent() + { + $frameworkResolver = $this->createFrameworkResolver(); + $this->tester->assertFalse($frameworkResolver->canResolve(HopefullyNonExistentClassOrInterface::class)); + } + + public function testCanResolveSingletones() + { + $frameworkResolver = $this->createFrameworkResolver(); + foreach ([ + Router::class, + \Pckg\Concept\Context::class, + Config::class, + Asset::class, + Meta::class, + Seo::class, + Flash::class, + Response::class, + Request::class, + Lang::class, + \Pckg\Auth\Entity\Adapter\Auth::class, + Locale::class, + ] as $class) { + $this->tester->assertTrue($frameworkResolver->canResolve($class), $class); + } + } + + public function testCanResolveExtendedSingletones() + { + $frameworkResolver = $this->createFrameworkResolver(); + foreach ([ + //Request\MockRequest::class, + //Response\MockResponse::class, + ] as $class) { + $this->tester->assertTrue($frameworkResolver->canResolve($class), $class); + } + } +} diff --git a/tests/unit/Framework/Router/Command/ResolveRouteCest.php b/tests/unit/Framework/Router/Command/ResolveRouteCest.php new file mode 100644 index 00000000..df20fe5d --- /dev/null +++ b/tests/unit/Framework/Router/Command/ResolveRouteCest.php @@ -0,0 +1,74 @@ +mockRouter(), '/'); + + $this->tester->assertNull($resolveRoute->execute()); + } + + public function testStaticRouteMissingView() + { + $router = $this->registerRoutes([ + '/' => [], + ]); + try { + $resolveRoute = new ResolveRoute($router, '/'); + $resolveRoute->execute(); + $this->throwException(); + } catch (\Throwable $e) { + $this->matchException('View not set.', $e); + } + } + + public function testMatchesSingle() + { + $router = $this->registerRoutes([ + '/' => [ + 'view' => fn() => null, + ], + ]); + $resolveRoute = new ResolveRoute($router, '/'); + $match = $resolveRoute->execute(); + $this->tester->assertTrue(isset($match['view'])); + unset($match['view']); + $expected = ['url' => '/', 'name' => null, 'domain' => null, 'method' => 'GET|POST']; + $this->tester->assertEquals($expected, array_union($expected, $match)); + } + + public function testMatchesCorrect() + { + $router = $this->registerRoutes([ + '/' => [ + 'view' => fn() => null, + ], + '/foo' => [ + 'view' => fn() => null, + ], + '/bar' => [ + 'view' => fn() => null, + ], + ]); + $resolveRoute = new ResolveRoute($router, '/foo'); + $match = $resolveRoute->execute(); + $this->tester->assertTrue(isset($match['view'])); + unset($match['view']); + $expected = ['url' => '/foo', 'name' => null, 'domain' => null, 'method' => 'GET|POST']; + $this->tester->assertEquals($expected, array_union($expected, $match)); + } +} diff --git a/tests/unit/RequestDataCest.php b/tests/unit/RequestDataCest.php index ad039050..e96e2247 100644 --- a/tests/unit/RequestDataCest.php +++ b/tests/unit/RequestDataCest.php @@ -1,19 +1,19 @@ mockFramework(); - } + use Cest; // tests public function defaultRequestDataTest(UnitTester $I) { + $_POST = []; + $_GET = []; + $_COOKIE = []; + $_REQUEST = []; + $request = new Pckg\Framework\Request(); $I->assertEquals([], $request->get()->all()); $I->assertEquals([], $request->post()->all());