diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml new file mode 100644 index 0000000..d03d072 --- /dev/null +++ b/.gitea/workflows/deploy.yaml @@ -0,0 +1,15 @@ +on: + push: + workflow_dispatch: +jobs: + deploy-job: + runs-on: server + steps: + - name: initial test + run: echo "test" + - name: get page + run: curl http://192.168.0.129:9001/update + - run: pwd + - run: cd ../ && pwd + - run: pwd + - run: cd /var/www/html/ryobi-crawler && bin/update \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 1820f9e..d4a6262 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.3-cli +FROM php:8.4-cli WORKDIR /usr/src/app ENV PHP_MEMORY_LIMIT=1500M diff --git a/bin/cacheclean b/bin/cacheclean index 3920b93..cb740c7 100755 --- a/bin/cacheclean +++ b/bin/cacheclean @@ -1,2 +1,4 @@ #!/usr/bin/env bash -bin/cli rm -rf var/cache \ No newline at end of file +echo "Cleaning cache" +bin/cli rm -rf var/cache +echo "cache cleaned2" \ No newline at end of file diff --git a/bin/update b/bin/update index 6c8b30a..8704895 100755 --- a/bin/update +++ b/bin/update @@ -2,4 +2,5 @@ echo "Updating project" git pull origin master bin/cacheclean +bin/composer install --no-dev echo "Project updated" \ No newline at end of file diff --git a/composer.json b/composer.json index 50d838e..684d92f 100644 --- a/composer.json +++ b/composer.json @@ -1,18 +1,18 @@ { "require": { - "guzzlehttp/guzzle": "^7.0", + "guzzlehttp/guzzle": "^7", "illuminate/database": "11.26.0.0", "ext-json": "*", - "symfony/console": "^7.0", - "symfony/routing": "^7.1", + "symfony/console": "^8.0", + "symfony/routing": "^8.0", "laravel/serializable-closure": "^1.3", - "symfony/http-kernel": "^7.1", - "symfony/framework-bundle": "^7.1", - "symfony/twig-bundle": "^7.1", - "symfony/dotenv": "^7.1", + "symfony/http-kernel": "^8.0", + "symfony/framework-bundle": "^8.0", + "symfony/twig-bundle": "^8.0", + "symfony/dotenv": "^8.0", "twig/intl-extra": "^3.13", "twig/extra-bundle": "^3.13", - "symfony/cache": "^7.2", + "symfony/cache": "^8.0", "twig/cache-extra": "^3.21" }, "autoload": { @@ -21,6 +21,7 @@ } }, "require-dev": { - "symfony/var-dumper": "^7.1" - } + "symfony/var-dumper": "^8.0" + }, + "minimum-stability": "stable" } diff --git a/composer.lock b/composer.lock index 7a84edd..88f4816 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ac693c1e5de8e9733f96954b8a0952b8", + "content-hash": "b6ca28a84dfeba67d5e93ac8d0eae924", "packages": [ { "name": "brick/math", @@ -1006,16 +1006,16 @@ }, { "name": "nesbot/carbon", - "version": "3.11.0", + "version": "3.11.1", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "bdb375400dcd162624531666db4799b36b64e4a1" + "reference": "f438fcc98f92babee98381d399c65336f3a3827f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/bdb375400dcd162624531666db4799b36b64e4a1", - "reference": "bdb375400dcd162624531666db4799b36b64e4a1", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/f438fcc98f92babee98381d399c65336f3a3827f", + "reference": "f438fcc98f92babee98381d399c65336f3a3827f", "shasum": "" }, "require": { @@ -1039,7 +1039,7 @@ "phpstan/extension-installer": "^1.4.3", "phpstan/phpstan": "^2.1.22", "phpunit/phpunit": "^10.5.53", - "squizlabs/php_codesniffer": "^3.13.4" + "squizlabs/php_codesniffer": "^3.13.4 || ^4.0.0" }, "bin": [ "bin/carbon" @@ -1082,14 +1082,14 @@ } ], "description": "An API extension for DateTime that supports 281 different languages.", - "homepage": "https://carbon.nesbot.com", + "homepage": "https://carbonphp.github.io/carbon/", "keywords": [ "date", "datetime", "time" ], "support": { - "docs": "https://carbon.nesbot.com/docs", + "docs": "https://carbonphp.github.io/carbon/guide/getting-started/introduction.html", "issues": "https://github.com/CarbonPHP/carbon/issues", "source": "https://github.com/CarbonPHP/carbon" }, @@ -1107,7 +1107,7 @@ "type": "tidelift" } ], - "time": "2025-12-02T21:04:28+00:00" + "time": "2026-01-29T09:26:29+00:00" }, { "name": "psr/cache", @@ -1616,34 +1616,30 @@ }, { "name": "symfony/cache", - "version": "v7.4.3", + "version": "v8.0.5", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "642117d18bc56832e74b68235359ccefab03dd11" + "reference": "92e9960386c7e01f58198038c199d522959a843c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/642117d18bc56832e74b68235359ccefab03dd11", - "reference": "642117d18bc56832e74b68235359ccefab03dd11", + "url": "https://api.github.com/repos/symfony/cache/zipball/92e9960386c7e01f58198038c199d522959a843c", + "reference": "92e9960386c7e01f58198038c199d522959a843c", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/cache": "^2.0|^3.0", "psr/log": "^1.1|^2|^3", "symfony/cache-contracts": "^3.6", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.4|^7.0|^8.0" + "symfony/var-exporter": "^7.4|^8.0" }, "conflict": { - "doctrine/dbal": "<3.6", + "doctrine/dbal": "<4.3", "ext-redis": "<6.1", - "ext-relay": "<0.12.1", - "symfony/dependency-injection": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/var-dumper": "<6.4" + "ext-relay": "<0.12.1" }, "provide": { "psr/cache-implementation": "2.0|3.0", @@ -1652,16 +1648,16 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/dbal": "^3.6|^4", + "doctrine/dbal": "^4.3", "predis/predis": "^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/filesystem": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "symfony/clock": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/filesystem": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -1696,7 +1692,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.4.3" + "source": "https://github.com/symfony/cache/tree/v8.0.5" }, "funding": [ { @@ -1716,7 +1712,7 @@ "type": "tidelift" } ], - "time": "2025-12-28T10:45:24+00:00" + "time": "2026-01-27T16:18:07+00:00" }, { "name": "symfony/cache-contracts", @@ -1796,22 +1792,21 @@ }, { "name": "symfony/clock", - "version": "v7.4.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110" + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/9169f24776edde469914c1e7a1442a50f7a4e110", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110", + "url": "https://api.github.com/repos/symfony/clock/zipball/832119f9b8dbc6c8e6f65f30c5969eca1e88764f", + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f", "shasum": "" }, "require": { - "php": ">=8.2", - "psr/clock": "^1.0", - "symfony/polyfill-php83": "^1.28" + "php": ">=8.4", + "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -1850,7 +1845,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.4.0" + "source": "https://github.com/symfony/clock/tree/v8.0.0" }, "funding": [ { @@ -1870,38 +1865,37 @@ "type": "tidelift" } ], - "time": "2025-11-12T15:39:26+00:00" + "time": "2025-11-12T15:46:48+00:00" }, { "name": "symfony/config", - "version": "v7.4.3", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "800ce889e358a53a9678b3212b0c8cecd8c6aace" + "reference": "8f45af92f08f82902827a8b6f403aaf49d893539" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/800ce889e358a53a9678b3212b0c8cecd8c6aace", - "reference": "800ce889e358a53a9678b3212b0c8cecd8c6aace", + "url": "https://api.github.com/repos/symfony/config/zipball/8f45af92f08f82902827a8b6f403aaf49d893539", + "reference": "8f45af92f08f82902827a8b6f403aaf49d893539", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^7.1|^8.0", - "symfony/polyfill-ctype": "~1.8" + "symfony/filesystem": "^7.4|^8.0", + "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/finder": "<6.4", "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -1929,7 +1923,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v7.4.3" + "source": "https://github.com/symfony/config/tree/v8.0.4" }, "funding": [ { @@ -1949,51 +1943,43 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:24:27+00:00" + "time": "2026-01-13T13:06:50+00:00" }, { "name": "symfony/console", - "version": "v7.4.3", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6" + "reference": "ace03c4cf9805080ff40cbeec69fca180c339a3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6", - "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6", + "url": "https://api.github.com/repos/symfony/console/zipball/ace03c4cf9805080ff40cbeec69fca180c339a3b", + "reference": "ace03c4cf9805080ff40cbeec69fca180c339a3b", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2|^8.0" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/lock": "<6.4", - "symfony/process": "<6.4" + "symfony/string": "^7.4|^8.0" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/lock": "^6.4|^7.0|^8.0", - "symfony/messenger": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2027,7 +2013,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.3" + "source": "https://github.com/symfony/console/tree/v8.0.4" }, "funding": [ { @@ -2047,43 +2033,40 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:50:43+00:00" + "time": "2026-01-13T13:06:50+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.4.3", + "version": "v8.0.5", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "54122901b6d772e94f1e71a75e0533bc16563499" + "reference": "40a6c455ade7e3bf25900d6b746d40cfa2573e26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/54122901b6d772e94f1e71a75e0533bc16563499", - "reference": "54122901b6d772e94f1e71a75e0533bc16563499", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/40a6c455ade7e3bf25900d6b746d40cfa2573e26", + "reference": "40a6c455ade7e3bf25900d6b746d40cfa2573e26", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/service-contracts": "^3.6", - "symfony/var-exporter": "^6.4.20|^7.2.5|^8.0" + "symfony/var-exporter": "^7.4|^8.0" }, "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<6.4", - "symfony/finder": "<6.4", - "symfony/yaml": "<6.4" + "ext-psr": "<1.1|>=2" }, "provide": { "psr/container-implementation": "1.1|2.0", "symfony/service-implementation": "1.1|2.0|3.0" }, "require-dev": { - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/config": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2111,7 +2094,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.4.3" + "source": "https://github.com/symfony/dependency-injection/tree/v8.0.5" }, "funding": [ { @@ -2131,7 +2114,7 @@ "type": "tidelift" } ], - "time": "2025-12-28T10:55:46+00:00" + "time": "2026-01-27T16:18:07+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2202,28 +2185,24 @@ }, { "name": "symfony/dotenv", - "version": "v7.4.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "1658a4d34df028f3d93bcdd8e81f04423925a364" + "reference": "460b4067a85288c59a59ce8c1bfb3942e71fd85c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/1658a4d34df028f3d93bcdd8e81f04423925a364", - "reference": "1658a4d34df028f3d93bcdd8e81f04423925a364", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/460b4067a85288c59a59ce8c1bfb3942e71fd85c", + "reference": "460b4067a85288c59a59ce8c1bfb3942e71fd85c", "shasum": "" }, "require": { - "php": ">=8.2" - }, - "conflict": { - "symfony/console": "<6.4", - "symfony/process": "<6.4" + "php": ">=8.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0" + "symfony/console": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2256,7 +2235,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v7.4.0" + "source": "https://github.com/symfony/dotenv/tree/v8.0.0" }, "funding": [ { @@ -2276,37 +2255,36 @@ "type": "tidelift" } ], - "time": "2025-11-16T10:14:42+00:00" + "time": "2025-11-16T10:17:21+00:00" }, { "name": "symfony/error-handler", - "version": "v7.4.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2" + "reference": "7620b97ec0ab1d2d6c7fb737aa55da411bea776a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/48be2b0653594eea32dcef130cca1c811dcf25c2", - "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/7620b97ec0ab1d2d6c7fb737aa55da411bea776a", + "reference": "7620b97ec0ab1d2d6c7fb737aa55da411bea776a", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/log": "^1|^2|^3", "symfony/polyfill-php85": "^1.32", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "symfony/var-dumper": "^7.4|^8.0" }, "conflict": { - "symfony/deprecation-contracts": "<2.5", - "symfony/http-kernel": "<6.4" + "symfony/deprecation-contracts": "<2.5" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", + "symfony/console": "^7.4|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ @@ -2338,7 +2316,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.4.0" + "source": "https://github.com/symfony/error-handler/tree/v8.0.4" }, "funding": [ { @@ -2358,28 +2336,28 @@ "type": "tidelift" } ], - "time": "2025-11-05T14:29:59+00:00" + "time": "2026-01-23T11:07:10+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.4.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d" + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9dddcddff1ef974ad87b3708e4b442dc38b2261d", - "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99301401da182b6cfaa4700dbe9987bb75474b47", + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", + "symfony/security-http": "<7.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -2388,14 +2366,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/error-handler": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/framework-bundle": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0|^8.0" + "symfony/stopwatch": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2423,7 +2401,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/v7.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.4" }, "funding": [ { @@ -2443,7 +2421,7 @@ "type": "tidelift" } ], - "time": "2025-10-28T09:38:46+00:00" + "time": "2026-01-05T11:45:55+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -2523,25 +2501,25 @@ }, { "name": "symfony/filesystem", - "version": "v7.4.0", + "version": "v8.0.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a" + "reference": "d937d400b980523dc9ee946bb69972b5e619058d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/d937d400b980523dc9ee946bb69972b5e619058d", + "reference": "d937d400b980523dc9ee946bb69972b5e619058d", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^6.4|^7.0|^8.0" + "symfony/process": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2569,7 +2547,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.0" + "source": "https://github.com/symfony/filesystem/tree/v8.0.1" }, "funding": [ { @@ -2589,27 +2567,27 @@ "type": "tidelift" } ], - "time": "2025-11-27T13:27:24+00:00" + "time": "2025-12-01T09:13:36+00:00" }, { "name": "symfony/finder", - "version": "v7.4.3", + "version": "v8.0.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06" + "reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/fffe05569336549b20a1be64250b40516d6e8d06", - "reference": "fffe05569336549b20a1be64250b40516d6e8d06", + "url": "https://api.github.com/repos/symfony/finder/zipball/8bd576e97c67d45941365bf824e18dc8538e6eb0", + "reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0|^8.0" + "symfony/filesystem": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2637,7 +2615,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.3" + "source": "https://github.com/symfony/finder/tree/v8.0.5" }, "funding": [ { @@ -2657,117 +2635,99 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:50:43+00:00" + "time": "2026-01-26T15:08:38+00:00" }, { "name": "symfony/framework-bundle", - "version": "v7.4.3", + "version": "v8.0.5", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "df908e8f9e5f6cc3c9e0d0172e030a5c1c280582" + "reference": "e2f9469e7a802dd7c0d193792afc494d68177c54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/df908e8f9e5f6cc3c9e0d0172e030a5c1c280582", - "reference": "df908e8f9e5f6cc3c9e0d0172e030a5c1c280582", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/e2f9469e7a802dd7c0d193792afc494d68177c54", + "reference": "e2f9469e7a802dd7c0d193792afc494d68177c54", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", "ext-xml": "*", - "php": ">=8.2", - "symfony/cache": "^6.4.12|^7.0|^8.0", - "symfony/config": "^7.4.3|^8.0.3", - "symfony/dependency-injection": "^7.4|^8.0", + "php": ">=8.4", + "symfony/cache": "^7.4|^8.0", + "symfony/config": "^7.4.4|^8.0.4", + "symfony/dependency-injection": "^7.4.4|^8.0.4", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^7.3|^8.0", - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/filesystem": "^7.1|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/filesystem": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", "symfony/http-foundation": "^7.4|^8.0", "symfony/http-kernel": "^7.4|^8.0", - "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-mbstring": "^1.0", "symfony/polyfill-php85": "^1.32", "symfony/routing": "^7.4|^8.0" }, "conflict": { "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/asset": "<6.4", - "symfony/asset-mapper": "<6.4", - "symfony/clock": "<6.4", - "symfony/console": "<6.4", - "symfony/dom-crawler": "<6.4", - "symfony/dotenv": "<6.4", + "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/console": "<7.4", "symfony/form": "<7.4", - "symfony/http-client": "<6.4", - "symfony/lock": "<6.4", - "symfony/mailer": "<6.4", + "symfony/json-streamer": "<7.4", "symfony/messenger": "<7.4", - "symfony/mime": "<6.4", - "symfony/property-access": "<6.4", - "symfony/property-info": "<6.4", - "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", - "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", - "symfony/security-core": "<6.4", - "symfony/security-csrf": "<7.2", - "symfony/serializer": "<7.2.5", - "symfony/stopwatch": "<6.4", - "symfony/translation": "<7.3", - "symfony/twig-bridge": "<6.4", - "symfony/twig-bundle": "<6.4", - "symfony/validator": "<6.4", - "symfony/web-profiler-bundle": "<6.4", - "symfony/webhook": "<7.2", + "symfony/security-csrf": "<7.4", + "symfony/serializer": "<7.4", + "symfony/translation": "<7.4", + "symfony/webhook": "<7.4", "symfony/workflow": "<7.4" }, "require-dev": { "doctrine/persistence": "^1.3|^2|^3", "dragonmantank/cron-expression": "^3.1", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0|^2.0", "seld/jsonlint": "^1.10", - "symfony/asset": "^6.4|^7.0|^8.0", - "symfony/asset-mapper": "^6.4|^7.0|^8.0", - "symfony/browser-kit": "^6.4|^7.0|^8.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/css-selector": "^6.4|^7.0|^8.0", - "symfony/dom-crawler": "^6.4|^7.0|^8.0", - "symfony/dotenv": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/asset": "^7.4|^8.0", + "symfony/asset-mapper": "^7.4|^8.0", + "symfony/browser-kit": "^7.4|^8.0", + "symfony/clock": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/css-selector": "^7.4|^8.0", + "symfony/dom-crawler": "^7.4|^8.0", + "symfony/dotenv": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", "symfony/form": "^7.4|^8.0", - "symfony/html-sanitizer": "^6.4|^7.0|^8.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/json-streamer": "^7.3|^8.0", - "symfony/lock": "^6.4|^7.0|^8.0", - "symfony/mailer": "^6.4|^7.0|^8.0", + "symfony/html-sanitizer": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/json-streamer": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/mailer": "^7.4|^8.0", "symfony/messenger": "^7.4|^8.0", - "symfony/mime": "^6.4|^7.0|^8.0", - "symfony/notifier": "^6.4|^7.0|^8.0", - "symfony/object-mapper": "^7.3|^8.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/property-info": "^6.4|^7.0|^8.0", - "symfony/rate-limiter": "^6.4|^7.0|^8.0", - "symfony/runtime": "^6.4.13|^7.1.6|^8.0", - "symfony/scheduler": "^6.4.4|^7.0.4|^8.0", - "symfony/security-bundle": "^6.4|^7.0|^8.0", - "symfony/semaphore": "^6.4|^7.0|^8.0", - "symfony/serializer": "^7.2.5|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/string": "^6.4|^7.0|^8.0", - "symfony/translation": "^7.3|^8.0", - "symfony/twig-bundle": "^6.4|^7.0|^8.0", - "symfony/type-info": "^7.1.8|^8.0", - "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/notifier": "^7.4|^8.0", + "symfony/object-mapper": "^7.4|^8.0", + "symfony/polyfill-intl-icu": "^1.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-info": "^7.4|^8.0", + "symfony/rate-limiter": "^7.4|^8.0", + "symfony/runtime": "^7.4|^8.0", + "symfony/scheduler": "^7.4|^8.0", + "symfony/security-bundle": "^7.4|^8.0", + "symfony/semaphore": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/string": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/twig-bundle": "^7.4|^8.0", + "symfony/type-info": "^7.4.1|^8.0.1", + "symfony/uid": "^7.4|^8.0", "symfony/validator": "^7.4|^8.0", - "symfony/web-link": "^6.4|^7.0|^8.0", - "symfony/webhook": "^7.2|^8.0", + "symfony/web-link": "^7.4|^8.0", + "symfony/webhook": "^7.4|^8.0", "symfony/workflow": "^7.4|^8.0", - "symfony/yaml": "^7.3|^8.0", - "twig/twig": "^3.12" + "symfony/yaml": "^7.4|^8.0" }, "type": "symfony-bundle", "autoload": { @@ -2795,7 +2755,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v7.4.3" + "source": "https://github.com/symfony/framework-bundle/tree/v8.0.5" }, "funding": [ { @@ -2815,41 +2775,39 @@ "type": "tidelift" } ], - "time": "2025-12-29T09:31:36+00:00" + "time": "2026-01-27T09:06:10+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.4.3", + "version": "v8.0.5", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52" + "reference": "e3422806e6f6760dbed0ddbc0a7fbfb6b5ce96bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a70c745d4cea48dbd609f4075e5f5cbce453bd52", - "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e3422806e6f6760dbed0ddbc0a7fbfb6b5ce96bb", + "reference": "e3422806e6f6760dbed0ddbc0a7fbfb6b5ce96bb", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.4", "symfony/polyfill-mbstring": "^1.1" }, "conflict": { - "doctrine/dbal": "<3.6", - "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + "doctrine/dbal": "<4.3" }, "require-dev": { - "doctrine/dbal": "^3.6|^4", + "doctrine/dbal": "^4.3", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5|^8.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/mime": "^6.4|^7.0|^8.0", - "symfony/rate-limiter": "^6.4|^7.0|^8.0" + "symfony/cache": "^7.4|^8.0", + "symfony/clock": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/rate-limiter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2877,7 +2835,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.3" + "source": "https://github.com/symfony/http-foundation/tree/v8.0.5" }, "funding": [ { @@ -2897,78 +2855,63 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:23:49+00:00" + "time": "2026-01-27T16:18:07+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.3", + "version": "v8.0.5", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "885211d4bed3f857b8c964011923528a55702aa5" + "reference": "20c1c5e41fc53928dbb670088f544f2d460d497d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/885211d4bed3f857b8c964011923528a55702aa5", - "reference": "885211d4bed3f857b8c964011923528a55702aa5", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/20c1c5e41fc53928dbb670088f544f2d460d497d", + "reference": "20c1c5e41fc53928dbb670088f544f2d460d497d", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^7.3|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", "symfony/http-foundation": "^7.4|^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/browser-kit": "<6.4", - "symfony/cache": "<6.4", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<6.4", "symfony/flex": "<2.10", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/translation": "<6.4", "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.4", - "symfony/validator": "<6.4", - "symfony/var-dumper": "<6.4", - "twig/twig": "<3.12" + "twig/twig": "<3.21" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0|^8.0", - "symfony/clock": "^6.4|^7.0|^8.0", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/css-selector": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/dom-crawler": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/browser-kit": "^7.4|^8.0", + "symfony/clock": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/css-selector": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/dom-crawler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/property-access": "^7.1|^8.0", - "symfony/routing": "^6.4|^7.0|^8.0", - "symfony/serializer": "^7.1|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/translation": "^6.4|^7.0|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/routing": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0|^8.0", - "symfony/validator": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0", - "twig/twig": "^3.12" + "symfony/uid": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0", + "symfony/var-exporter": "^7.4|^8.0", + "twig/twig": "^3.21" }, "type": "library", "autoload": { @@ -2996,7 +2939,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.4.3" + "source": "https://github.com/symfony/http-kernel/tree/v8.0.5" }, "funding": [ { @@ -3016,32 +2959,31 @@ "type": "tidelift" } ], - "time": "2025-12-31T08:43:57+00:00" + "time": "2026-01-28T10:46:31+00:00" }, { "name": "symfony/intl", - "version": "v7.4.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "2fa074de6c7faa6b54f2891fc22708f42245ed5c" + "reference": "8d049269c2accca0b02e5f9de39f3ee92ebc4468" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/2fa074de6c7faa6b54f2891fc22708f42245ed5c", - "reference": "2fa074de6c7faa6b54f2891fc22708f42245ed5c", + "url": "https://api.github.com/repos/symfony/intl/zipball/8d049269c2accca0b02e5f9de39f3ee92ebc4468", + "reference": "8d049269c2accca0b02e5f9de39f3ee92ebc4468", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.4" }, "conflict": { - "symfony/string": "<7.1" + "symfony/string": "<7.4" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0|^8.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0" + "symfony/filesystem": "^7.4|^8.0", + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3086,7 +3028,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v7.4.0" + "source": "https://github.com/symfony/intl/tree/v8.0.4" }, "funding": [ { @@ -3106,7 +3048,7 @@ "type": "tidelift" } ], - "time": "2025-11-27T13:27:24+00:00" + "time": "2026-01-12T12:37:40+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3443,86 +3385,6 @@ ], "time": "2024-12-23T08:48:59+00:00" }, - { - "name": "symfony/polyfill-php83", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" - }, - "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 backporting some PHP 8.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-08T02:45:35+00:00" - }, { "name": "symfony/polyfill-php85", "version": "v1.33.0", @@ -3605,34 +3467,29 @@ }, { "name": "symfony/routing", - "version": "v7.4.3", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090" + "reference": "4a2bc08d1c35307239329f434d45c2bfe8241fa9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090", - "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090", + "url": "https://api.github.com/repos/symfony/routing/zipball/4a2bc08d1c35307239329f434d45c2bfe8241fa9", + "reference": "4a2bc08d1c35307239329f434d45c2bfe8241fa9", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3" }, - "conflict": { - "symfony/config": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/yaml": "<6.4" - }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3666,7 +3523,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.3" + "source": "https://github.com/symfony/routing/tree/v8.0.4" }, "funding": [ { @@ -3686,7 +3543,7 @@ "type": "tidelift" } ], - "time": "2025-12-19T10:00:43+00:00" + "time": "2026-01-12T12:37:40+00:00" }, { "name": "symfony/service-contracts", @@ -3777,35 +3634,34 @@ }, { "name": "symfony/string", - "version": "v7.4.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003" + "reference": "758b372d6882506821ed666032e43020c4f57194" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003", - "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003", + "url": "https://api.github.com/repos/symfony/string/zipball/758b372d6882506821ed666032e43020c4f57194", + "reference": "758b372d6882506821ed666032e43020c4f57194", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.33", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1|^8.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0" + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3844,7 +3700,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.0" + "source": "https://github.com/symfony/string/tree/v8.0.4" }, "funding": [ { @@ -3864,38 +3720,31 @@ "type": "tidelift" } ], - "time": "2025-11-27T13:27:24+00:00" + "time": "2026-01-12T12:37:40+00:00" }, { "name": "symfony/translation", - "version": "v7.4.3", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d" + "reference": "db70c8ce7db74fd2da7b1d268db46b2a8ce32c10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/7ef27c65d78886f7599fdd5c93d12c9243ecf44d", - "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d", + "url": "https://api.github.com/repos/symfony/translation/zipball/db70c8ce7db74fd2da7b1d268db46b2a8ce32c10", + "reference": "db70c8ce7db74fd2da7b1d268db46b2a8ce32c10", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5.3|^3.3" + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation-contracts": "^3.6.1" }, "conflict": { "nikic/php-parser": "<5.0", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<6.4", - "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<6.4", - "symfony/yaml": "<6.4" + "symfony/service-contracts": "<2.5" }, "provide": { "symfony/translation-implementation": "2.3|3.0" @@ -3903,17 +3752,17 @@ "require-dev": { "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/routing": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3944,7 +3793,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.4.3" + "source": "https://github.com/symfony/translation/tree/v8.0.4" }, "funding": [ { @@ -3964,7 +3813,7 @@ "type": "tidelift" } ], - "time": "2025-12-29T09:31:36+00:00" + "time": "2026-01-13T13:06:50+00:00" }, { "name": "symfony/translation-contracts", @@ -4050,67 +3899,59 @@ }, { "name": "symfony/twig-bridge", - "version": "v7.4.3", + "version": "v8.0.5", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "43c922fce020060c65b0fd54bfd8def3b38949b6" + "reference": "3e60c35cb47b1077524c066ec277eaf92cdc2393" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/43c922fce020060c65b0fd54bfd8def3b38949b6", - "reference": "43c922fce020060c65b0fd54bfd8def3b38949b6", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/3e60c35cb47b1077524c066ec277eaf92cdc2393", + "reference": "3e60c35cb47b1077524c066ec277eaf92cdc2393", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.4", "symfony/translation-contracts": "^2.5|^3", "twig/twig": "^3.21" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/console": "<6.4", - "symfony/form": "<6.4", - "symfony/http-foundation": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/mime": "<6.4", - "symfony/serializer": "<6.4", - "symfony/translation": "<6.4", - "symfony/workflow": "<6.4" + "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/form": "<7.4.4|>8.0,<8.0.4" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3|^4", "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^6.4|^7.0|^8.0", - "symfony/asset-mapper": "^6.4|^7.0|^8.0", - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/emoji": "^7.1|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", - "symfony/form": "^6.4.30|~7.3.8|^7.4.1|^8.0.1", - "symfony/html-sanitizer": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^7.3|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/intl": "^6.4|^7.0|^8.0", - "symfony/mime": "^6.4|^7.0|^8.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/property-info": "^6.4|^7.0|^8.0", - "symfony/routing": "^6.4|^7.0|^8.0", + "phpdocumentor/reflection-docblock": "^5.2", + "symfony/asset": "^7.4|^8.0", + "symfony/asset-mapper": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", + "symfony/form": "^7.4.4|^8.0.4", + "symfony/html-sanitizer": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/polyfill-intl-icu": "^1.0", + "symfony/property-info": "^7.4|^8.0", + "symfony/routing": "^7.4|^8.0", "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^6.4|^7.0|^8.0", - "symfony/security-csrf": "^6.4|^7.0|^8.0", - "symfony/security-http": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4.3|^7.0.3|^8.0", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/translation": "^6.4|^7.0|^8.0", - "symfony/validator": "^6.4|^7.0|^8.0", - "symfony/web-link": "^6.4|^7.0|^8.0", - "symfony/workflow": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0", + "symfony/security-core": "^7.4|^8.0", + "symfony/security-csrf": "^7.4|^8.0", + "symfony/security-http": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/web-link": "^7.4|^8.0", + "symfony/workflow": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0", "twig/cssinliner-extra": "^3", "twig/inky-extra": "^3", "twig/markdown-extra": "^3" @@ -4141,7 +3982,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v7.4.3" + "source": "https://github.com/symfony/twig-bridge/tree/v8.0.5" }, "funding": [ { @@ -4161,49 +4002,43 @@ "type": "tidelift" } ], - "time": "2025-12-16T08:02:06+00:00" + "time": "2026-01-27T09:06:10+00:00" }, { "name": "symfony/twig-bundle", - "version": "v7.4.3", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "9e1f5fd2668ed26c60d17d63f15fe270ed8da5e6" + "reference": "5a68f2e0e06996514bf04900c3982b93b42487af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/9e1f5fd2668ed26c60d17d63f15fe270ed8da5e6", - "reference": "9e1f5fd2668ed26c60d17d63f15fe270ed8da5e6", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/5a68f2e0e06996514bf04900c3982b93b42487af", + "reference": "5a68f2e0e06996514bf04900c3982b93b42487af", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", - "php": ">=8.2", + "php": ">=8.4", "symfony/config": "^7.4|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0", - "symfony/twig-bridge": "^7.3|^8.0", - "twig/twig": "^3.12" - }, - "conflict": { - "symfony/framework-bundle": "<6.4", - "symfony/translation": "<6.4" + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/twig-bridge": "^7.4|^8.0" }, "require-dev": { - "symfony/asset": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", - "symfony/form": "^6.4|^7.0|^8.0", - "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0", - "symfony/routing": "^6.4|^7.0|^8.0", - "symfony/runtime": "^6.4.13|^7.1.6", - "symfony/stopwatch": "^6.4|^7.0|^8.0", - "symfony/translation": "^6.4|^7.0|^8.0", - "symfony/web-link": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0" + "symfony/asset": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", + "symfony/form": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/routing": "^7.4|^8.0", + "symfony/runtime": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/web-link": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "type": "symfony-bundle", "autoload": { @@ -4231,7 +4066,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v7.4.3" + "source": "https://github.com/symfony/twig-bundle/tree/v8.0.4" }, "funding": [ { @@ -4251,35 +4086,35 @@ "type": "tidelift" } ], - "time": "2025-12-19T10:00:43+00:00" + "time": "2026-01-06T12:43:21+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.4.3", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7e99bebcb3f90d8721890f2963463280848cba92" + "reference": "326e0406fc315eca57ef5740fa4a280b7a068c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7e99bebcb3f90d8721890f2963463280848cba92", - "reference": "7e99bebcb3f90d8721890f2963463280848cba92", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/326e0406fc315eca57ef5740fa4a280b7a068c82", + "reference": "326e0406fc315eca57ef5740fa4a280b7a068c82", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { - "symfony/console": "<6.4" + "symfony/console": "<7.4", + "symfony/error-handler": "<7.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/process": "^6.4|^7.0|^8.0", - "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/uid": "^7.4|^8.0", "twig/twig": "^3.12" }, "bin": [ @@ -4318,7 +4153,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.3" + "source": "https://github.com/symfony/var-dumper/tree/v8.0.4" }, "funding": [ { @@ -4338,30 +4173,29 @@ "type": "tidelift" } ], - "time": "2025-12-18T07:04:31+00:00" + "time": "2026-01-01T23:07:29+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.4.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "03a60f169c79a28513a78c967316fbc8bf17816f" + "reference": "7345f46c251f2eb27c7b3ebdb5bb076b3ffcae04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/03a60f169c79a28513a78c967316fbc8bf17816f", - "reference": "03a60f169c79a28513a78c967316fbc8bf17816f", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/7345f46c251f2eb27c7b3ebdb5bb076b3ffcae04", + "reference": "7345f46c251f2eb27c7b3ebdb5bb076b3ffcae04", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.4" }, "require-dev": { - "symfony/property-access": "^6.4|^7.0|^8.0", - "symfony/serializer": "^6.4|^7.0|^8.0", - "symfony/var-dumper": "^6.4|^7.0|^8.0" + "symfony/property-access": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -4399,7 +4233,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.4.0" + "source": "https://github.com/symfony/var-exporter/tree/v8.0.0" }, "funding": [ { @@ -4419,20 +4253,20 @@ "type": "tidelift" } ], - "time": "2025-09-11T10:15:23+00:00" + "time": "2025-11-05T18:53:00+00:00" }, { "name": "twig/cache-extra", - "version": "v3.22.1", + "version": "v3.23.0", "source": { "type": "git", "url": "https://github.com/twigphp/cache-extra.git", - "reference": "043bd496ada6bf2f73ed3186434fd9e6479a1b8d" + "reference": "c85c6ca1142db2f1f4f8c853988aef560d064199" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/cache-extra/zipball/043bd496ada6bf2f73ed3186434fd9e6479a1b8d", - "reference": "043bd496ada6bf2f73ed3186434fd9e6479a1b8d", + "url": "https://api.github.com/repos/twigphp/cache-extra/zipball/c85c6ca1142db2f1f4f8c853988aef560d064199", + "reference": "c85c6ca1142db2f1f4f8c853988aef560d064199", "shasum": "" }, "require": { @@ -4472,7 +4306,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/cache-extra/tree/v3.22.1" + "source": "https://github.com/twigphp/cache-extra/tree/v3.23.0" }, "funding": [ { @@ -4484,20 +4318,20 @@ "type": "tidelift" } ], - "time": "2025-11-02T11:00:49+00:00" + "time": "2025-12-02T14:45:16+00:00" }, { "name": "twig/extra-bundle", - "version": "v3.22.2", + "version": "v3.23.0", "source": { "type": "git", "url": "https://github.com/twigphp/twig-extra-bundle.git", - "reference": "09de9be7f6c0d19ede7b5a1dbfcfb2e9d1e0ea9e" + "reference": "7a27e784dc56eddfef5e9295829b290ce06f1682" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/09de9be7f6c0d19ede7b5a1dbfcfb2e9d1e0ea9e", - "reference": "09de9be7f6c0d19ede7b5a1dbfcfb2e9d1e0ea9e", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/7a27e784dc56eddfef5e9295829b290ce06f1682", + "reference": "7a27e784dc56eddfef5e9295829b290ce06f1682", "shasum": "" }, "require": { @@ -4546,7 +4380,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.22.2" + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.23.0" }, "funding": [ { @@ -4558,20 +4392,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T08:51:53+00:00" + "time": "2025-12-18T20:46:15+00:00" }, { "name": "twig/intl-extra", - "version": "v3.22.1", + "version": "v3.23.0", "source": { "type": "git", "url": "https://github.com/twigphp/intl-extra.git", - "reference": "93ac31e53cdd3f2e541f42690cd0c54ca8138ab1" + "reference": "32f15a38d45a8d0ec11bc8a3d97d3ac2a261499f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/93ac31e53cdd3f2e541f42690cd0c54ca8138ab1", - "reference": "93ac31e53cdd3f2e541f42690cd0c54ca8138ab1", + "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/32f15a38d45a8d0ec11bc8a3d97d3ac2a261499f", + "reference": "32f15a38d45a8d0ec11bc8a3d97d3ac2a261499f", "shasum": "" }, "require": { @@ -4610,7 +4444,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/intl-extra/tree/v3.22.1" + "source": "https://github.com/twigphp/intl-extra/tree/v3.23.0" }, "funding": [ { @@ -4622,20 +4456,20 @@ "type": "tidelift" } ], - "time": "2025-11-02T11:00:49+00:00" + "time": "2026-01-17T13:57:47+00:00" }, { "name": "twig/twig", - "version": "v3.22.2", + "version": "v3.23.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "946ddeafa3c9f4ce279d1f34051af041db0e16f2" + "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/946ddeafa3c9f4ce279d1f34051af041db0e16f2", - "reference": "946ddeafa3c9f4ce279d1f34051af041db0e16f2", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", + "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", "shasum": "" }, "require": { @@ -4689,7 +4523,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.22.2" + "source": "https://github.com/twigphp/Twig/tree/v3.23.0" }, "funding": [ { @@ -4701,7 +4535,7 @@ "type": "tidelift" } ], - "time": "2025-12-14T11:28:47+00:00" + "time": "2026-01-23T21:00:41+00:00" }, { "name": "voku/portable-ascii", @@ -4788,5 +4622,5 @@ "ext-json": "*" }, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/src/Command/CacheWarmCommand.php b/src/Command/CacheWarmCommand.php deleted file mode 100644 index 6e6d618..0000000 --- a/src/Command/CacheWarmCommand.php +++ /dev/null @@ -1,84 +0,0 @@ -cache->clear(); - - $capsule = new Capsule; - $capsule->addConnection([ - 'driver' => 'sqlite', - 'database' => __DIR__ . '/../../database.sqlite', - ]); - $capsule->setAsGlobal(); - $capsule->bootEloquent(); - - $progress = new ProgressBar($output); - $progress->start(); - $products = Product::with([ - 'price' => fn($query) => $query->orderByDesc('created_at'), - 'stock' => fn($query) => $query->orderByDesc('created_at'), - ])->get(); - $progress->setMaxSteps(count($products)); - - $request = Request::create('/cache-warm'); - $this->requestStack->push($request); - - foreach ($products as $product) { - $priceList = $product->price()->pluck('price'); - $stockList = $product->stock()->pluck('stock'); - $priceDates = $product->price()->pluck('created_at')->map(fn($date) => $date->format('Y-m-d'))->toArray(); - $stockDates = $product->stock()->pluck('created_at')->map(fn($date) => $date->format('Y-m-d'))->toArray(); - $this->twig->render('product.html.twig', [ - 'product' => $product, - 'price_list' => $this->prepareChartData($priceDates, $priceList), - 'stock_list' => $this->prepareChartData($stockDates, $stockList), - 'price_dates' => implode("','", $priceDates), - ]); - $progress->advance(); - } - - $progress->finish(); - $output->writeln(''); - $output->writeln('DONE'); - - return Command::SUCCESS; - } - - private function prepareChartData($set1, $set2): string - { - $data = []; - foreach ($set1 as $key => $value) { - $data[] = ['x' => $value, 'y' => $set2[$key]]; - } - $stringData = json_encode($data); - - return str_replace(['"x"', '"y"'], ['x', 'y'], $stringData); - } -} diff --git a/src/Command/Migrate.php b/src/Command/Migrate.php index 1a6890c..434e768 100644 --- a/src/Command/Migrate.php +++ b/src/Command/Migrate.php @@ -112,7 +112,7 @@ class Migrate extends Command 'productsUrl' => 'https://uk.ryobitools.eu/api/product-listing/get-products', 'cultureCode' => 'en-GB', 'currency' => 'GBP', - 'locale' => 'en', + 'locale' => 'uk', 'created_at' => now(), 'updated_at' => now(), ] @@ -154,6 +154,30 @@ class Migrate extends Command ] ); } + if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Poland')->exists()) { + $id = Capsule::table('countries')->insertGetId( + [ + 'countryName' => 'Poland', + 'productsUrl' => 'https://pl.ryobitools.eu/api/product-listing/get-products', + 'cultureCode' => 'pl-PL', + 'currency' => 'PLN', + 'locale' => 'pl', + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'UK')->exists()) { + Capsule::table('countries')->insert([ + 'countryName' => 'UK', + 'productsUrl' => 'https://uk.ryobitools.eu/api/product-listing/get-products', + 'cultureCode' => 'en-GB', + 'currency' => 'GBP', + 'locale' => 'uk', + 'created_at' => now(), + 'updated_at' => now(), + ] + ); + } if (!Capsule::schema()->hasColumn('products', 'country_id')) { Capsule::schema()->table('products', function (Blueprint $table) use ($id) { @@ -211,15 +235,78 @@ class Migrate extends Command $table->date('lastSeen')->nullable(); }); } + + if (!Capsule::schema()->hasColumn('products', 'stock')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->integer('stock')->nullable(); + }); + } + if (!Capsule::schema()->hasColumn('products', 'promotions')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->json('promotions')->nullable(); + }); + } } public function index(): void { - if (!count(Capsule::select('SELECT name FROM sqlite_master WHERE type = "index" and name = "products_skuid_country_id_unique"'))) { + if (!$this->hasIndex('products_skuid_country_id_unique')) { Capsule::schema()->table('products', function (Blueprint $table) { - $table->integer('skuID')->unique(false)->change(); + if ($this->hasIndex('products_skuid_unique')) { + $table->integer('skuID')->unique(false)->change(); + } $table->unique(['skuID', 'country_id']); }); } + + if (!$this->hasIndex('prices_product_id_index')) { + Capsule::schema()->table('prices', function (Blueprint $table) { + $table->index('product_id'); + }); + } + + if (!$this->hasIndex('products_id_index')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->index('id'); + }); + } + + if (!$this->hasIndex('stocks_product_id_stock_index')) { + Capsule::schema()->table('stocks', function (Blueprint $table) { + $table->index(['product_id', 'stock']); + }); + } + + if (!$this->isFK('products', 'id', 'stocks', 'product_id')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->foreign('id')->references('product_id')->on('stocks'); + }); + } + + if (!$this->isFK('products', 'id', 'prices', 'product_id')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->foreign('id')->references('product_id')->on('prices'); + }); + } + if (!$this->isFK('products', 'country_id', 'countries', 'id')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->foreign('country_id')->references('id')->on('countries'); + }); + } + } + + private function isFK(string $table, string $column, string $fTable, string $fColumn): bool + { + $fkColumns = Capsule::schema()->getForeignKeys($table); + + return !empty(array_filter($fkColumns, fn($fkColumn) => ($fkColumn['foreign_table'] == $fTable && + in_array($fColumn, $fkColumn['foreign_columns']) && + in_array($column, $fkColumn['columns'])) + )); + } + + private function hasIndex(string $indexName): bool + { + return !!count(Capsule::select('SELECT name FROM sqlite_master WHERE type = "index" and name = ?', [$indexName])); } } diff --git a/src/Command/ScrapeWebsite.php b/src/Command/ScrapeWebsite.php index 9993707..8178b64 100644 --- a/src/Command/ScrapeWebsite.php +++ b/src/Command/ScrapeWebsite.php @@ -15,11 +15,13 @@ use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; #[AsCommand(name: 'app:scrape', description: 'Scrape all products from Ryobi website')] class ScrapeWebsite extends Command { + const COUNTRY_ID = 'country'; private Client $client; public function __construct(protected Capsule $database) @@ -30,39 +32,42 @@ class ScrapeWebsite extends Command protected function configure(): void { $this->client = new Client(); + $this->addOption(self::COUNTRY_ID, 'c', InputOption::VALUE_OPTIONAL, 'Country id'); } public function execute(InputInterface $input, OutputInterface $output): int { + $countryId = intval($input->getOption(self::COUNTRY_ID)); $output->writeln('Scrape products'); - $progress = new ProgressBar($output); - $countries = Country::all(); + $countries = Country::all()->when($countryId, fn ($query) => $query->where('id', $countryId)); foreach($countries as $country) { - $output->writeln('Country name: ' . $country->countryName."\n"); - $progress->start(); + $output->writeln('Country name: ' . $country->countryName); $products = $this->getProducts($country); + $progress = new ProgressBar($output); + $progress->start(); $progress->setMaxSteps(count($products)); foreach ($products as $product) { $this->saveProduct($product, $country); $progress->advance(); } $progress->finish(); - $output->writeln(''); - $output->writeln('Scrape products - DONE'); - $output->writeln(''); + $output->writeln("\nScrape products - DONE\n"); } $output->writeln('Update prices'); $products = Product::all(); + $progress = new ProgressBar($output); $progress->setMaxSteps(count($products)); $progress->start(); foreach($products as $product) { $newestPrice = $product->newestPrice; + $currentStock = $product->currentStock; $product->priceCurrent = $newestPrice->price; $product->productStandardPrice = $newestPrice->productStandardPrice; $product->lowestProductPrice30Days = $newestPrice->lowestProductPrice30Days; $product->priceLowest = $product->lowestPrice->price; $product->lastSeen = $newestPrice->created_at->format('Y-m-d'); + $product->stock = $currentStock->stock; $product->save(['timestamps' => false]); $progress->advance(); } @@ -93,7 +98,7 @@ class ScrapeWebsite extends Command $products = array_merge($products, $responseObject->products); $page++; $canLoadMore = $responseObject->canLoadMore; - } catch (GuzzleException) { + } catch (GuzzleException $e) { return $products; } } while ($canLoadMore); @@ -103,17 +108,13 @@ class ScrapeWebsite extends Command private function saveProduct(\stdClass $product, Country $country): void { -// if ($product->skuID == 0) { -// dump([$product->skuID, $product->name]); -// } -// return; /** @var Product $productModel */ $productModel = Product::firstOrNew(['skuID' => $product->skuID, 'country_id' => $country->id]); $productModel->skuID = $product->skuID; $productModel->name = $product->name; $productModel->availableQuantity = $product->availableQuantity; - $productModel->categories = $product->categories; + $productModel->categories = str_replace(['/', ' '], '', $product->categories); $productModel->image = $product->image; $productModel->subTitle = $product->subTitle; $productModel->variantCode = $product->variantCode; @@ -122,6 +123,7 @@ class ScrapeWebsite extends Command $productModel->lastSeen = date("Y-m-d"); $productModel->touch('updated_at'); $productModel->country()->associate($country); + $productModel->promotions = $product->promotions; $productModel->save(); $priceExists = $productModel->price()->whereRaw("strftime('%Y-%m-%d', created_at) = ?", [date('Y-m-d')])->exists(); diff --git a/src/Controller/BaseController.php b/src/Controller/BaseController.php index dfccd17..81aa2af 100644 --- a/src/Controller/BaseController.php +++ b/src/Controller/BaseController.php @@ -11,7 +11,7 @@ class BaseController extends AbstractController { protected Environment $twig; - public function __construct(protected FilesystemAdapter $cache, protected Capsule $database) + public function __construct( protected Capsule $database) { } } diff --git a/src/Controller/CategoryController.php b/src/Controller/CategoryController.php index 27c190b..f8659cb 100644 --- a/src/Controller/CategoryController.php +++ b/src/Controller/CategoryController.php @@ -8,22 +8,40 @@ use Symfony\Component\Routing\Attribute\Route; final class CategoryController extends BaseController { - #[Route('/category/{category}', name: 'app_category')] - public function __invoke(string $category): Response + #[Route('/category/{category?}', name: 'app_category')] + public function __invoke(?string $category): Response { - if($this->cache->getItem('list_category_'.$category)->isHit()) { - return $this->render('productList.html.twig', ['listType' => 'category_'.$category]); - } + /** @var Product[] $products */ $products = Product::with(['price', 'lowestPrice']) ->selectRaw('products.*') ->distinct('products.id') + ->when(!is_null($category) , fn ($q) => $q->whereRaw('json_each.value = ?', [$category])) ->fromRaw('products, json_each(products.categories)') - ->whereRaw('json_each.value = ?', [$category]) ->orderByDesc('starred') ->orderByDesc('created_by') ->get(); - return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'category_'.$category]); + $categoriesTree = []; + + foreach ($products as $product) { + $categoriesTree = $this->addToTree($product->categories, $categoriesTree); + } + + return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'category_' . $category, 'category' => $category, 'categoryTree' => $categoriesTree]); + } + + private function addToTree(array $categories, mixed $categoriesTree) + { + $tmp = &$categoriesTree; + foreach ($categories as $category) { + if (empty($tmp[$category])) { + $tmp[$category] = ['count' => 0]; + } + $tmp = &$tmp[$category]; + $tmp['count']++; + } + + return $categoriesTree; } } diff --git a/src/Controller/DiscontinuedController.php b/src/Controller/DiscontinuedController.php index 4c5b96b..d8f60b3 100644 --- a/src/Controller/DiscontinuedController.php +++ b/src/Controller/DiscontinuedController.php @@ -13,9 +13,6 @@ final class DiscontinuedController extends BaseController #[Route('/discontinued', name: 'app_discontinued')] public function __invoke(): Response { - if($this->cache->getItem('list_discontinued')->isHit()) { - return $this->render('productList.html.twig', ['listType' => 'discontinued']); - } $products = Product::where('lastSeen', '<', now()->format('Y-m-d')) ->orderByDesc('starred') diff --git a/src/Controller/IndexController.php b/src/Controller/IndexController.php index 759236c..a1442e7 100644 --- a/src/Controller/IndexController.php +++ b/src/Controller/IndexController.php @@ -11,14 +11,11 @@ final class IndexController extends BaseController #[Route('/', name: 'app_home')] public function __invoke(): Response { - if ($this->cache->getItem('list_all')->isHit()) { - return $this->render('productList.html.twig', ['listType' => 'all']); - } - $products = Product::with(['currentStock']) - ->orderByDesc('starred') + $products = Product::orderByDesc('starred') ->orderByDesc('created_by') ->get(); + return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'all']); } } diff --git a/src/Controller/LowestPriceController.php b/src/Controller/LowestPriceController.php index 66a1808..9c038e4 100644 --- a/src/Controller/LowestPriceController.php +++ b/src/Controller/LowestPriceController.php @@ -13,9 +13,6 @@ final class LowestPriceController extends BaseController public function __invoke(): Response { $listType = 'lowest_price'; - if($this->cache->getItem('lowest_price')->isHit()) { - return $this->render('productList.html.twig', ['listType' => $listType]); - } $products = Product::whereRaw('priceCurrent = priceLowest') ->whereRaw('lastSeen = "'.now()->format('Y-m-d').'"') diff --git a/src/Controller/NewController.php b/src/Controller/NewController.php index cf1f3ee..87077c0 100644 --- a/src/Controller/NewController.php +++ b/src/Controller/NewController.php @@ -13,14 +13,11 @@ final class NewController extends BaseController #[Route('/new', name: 'app_new')] public function __invoke(): Response { - if($this->cache->getItem('list_new')->isHit()) { - return $this->render('productList.html.twig', ['listType' => 'new']); - } - - $products = Product::where('created_at', '>', now()->modify('-30 days')->format('Y-m-d')) + $date = now()->modify('-30 days')->format('Y-m-d'); + $products = Product::where('created_at', '>', $date) + ->with(['country', 'stock']) ->orderByDesc('starred') ->orderByDesc('created_by') - ->with(['currentPrice', 'lowestPrice']) ->get(); return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'new']); } diff --git a/src/Controller/ProductController.php b/src/Controller/ProductController.php index 9bdbc65..408b0c7 100644 --- a/src/Controller/ProductController.php +++ b/src/Controller/ProductController.php @@ -19,10 +19,6 @@ final class ProductController extends BaseController #[Route('/product/{productId<\d+>}', name: 'app_product')] public function __invoke(int $productId): Response { - if ($this->cache->getItem('product' . $productId)->isHit()) { - return $this->render('product.html.twig', ['product' => ['id' => $productId]]); - } - $product = Product::with([ 'price' => fn($query) => $query->orderBy('created_at', 'desc'), 'stock' => fn($query) => $query->orderBy('created_at', 'desc'), @@ -32,6 +28,10 @@ final class ProductController extends BaseController } $priceList = $product->price()->pluck('price', 'created_at')->mapWithKeys(fn($price, $createdAt) => [explode(' ', $createdAt)[0] => $price])->toArray(); $stockList = $product->stock()->pluck('stock', 'created_at')->mapWithKeys(fn($stock, $createdAt) => [explode(' ', $createdAt)[0] => $stock])->toArray(); + + ksort($stockList); + ksort($priceList); + return $this->render('product.html.twig', [ 'product' => $product, 'price_list' => $this->prepareChartData($priceList), diff --git a/src/Controller/PromosController.php b/src/Controller/PromosController.php index b54bc74..f3f277f 100644 --- a/src/Controller/PromosController.php +++ b/src/Controller/PromosController.php @@ -8,18 +8,21 @@ use Symfony\Component\Routing\Attribute\Route; final class PromosController extends BaseController { - #[Route('/promos', name: 'app_promos')] - public function __invoke(): Response + #[Route('/promos/{promo?}', name: 'app_promos')] + public function __invoke(?string $promo): Response { - if($this->cache->getItem('list_promos')->isHit()) { - return $this->render('productList.html.twig', ['listType' => 'promos']); - } - - $products = Product::whereRaw('priceCurrent < productStandardPrice') + $products = Product::when(is_null($promo), fn($q) => $q->whereRaw('priceCurrent < productStandardPrice')) ->orderByDesc('starred') ->orderByDesc('created_by') ->with(['currentPrice', 'lowestPrice']) + ->when(!is_null($promo), fn($q) => $q->whereRaw("json_extract(promotions, '$.slug') LIKE ?", $promo)) ->get(); - return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'promos']); + + + $promos = Product::select($this->database->getConnection()->raw("distinct json_extract(promotions, '$.slug') as slug, json_extract(promotions, '$.tag') as tag")) + ->whereRaw("json_extract(promotions, '$.tag') is not null") + ->get(); + + return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'promos' . $promo, 'promos' => $promos->toArray()]); } } diff --git a/src/Controller/StarController.php b/src/Controller/StarController.php index af63187..6fe1930 100644 --- a/src/Controller/StarController.php +++ b/src/Controller/StarController.php @@ -12,15 +12,12 @@ final class StarController extends BaseController #[Route('/star/{productId<\d+>}', name: 'app_star')] public function __invoke(int $productId, Request $request): Response { - $this->cache->deleteItems(['list_all', 'list_promos', 'list_new', 'list_discontinued']); $referer = $request->headers->get('referer'); if (str_contains($referer, '/category/')) { preg_match('#/category/(.*)#i', $referer, $matches); - $this->cache->deleteItem('list_category_'.urldecode($matches[1])); } if (str_contains($referer, '/search?search=')) { preg_match('#/search\?search=(.*)#i', $referer, $matches); - $this->cache->deleteItem('list_search_'.urldecode($matches[1])); } Product::find($productId)->toggleStarred()->save(); diff --git a/src/Controller/UpdateController.php b/src/Controller/UpdateController.php new file mode 100644 index 0000000..c7a907c --- /dev/null +++ b/src/Controller/UpdateController.php @@ -0,0 +1,18 @@ +set(Manager::class)->configurator([DatabaseFactory::class, 'create']); $services->load('Krzysiej\\RyobiCrawler\\', __DIR__ ) ->exclude('../src/{Models,Twig,DatabaseFactory.php,Kernel.php}'); - $services->set('twig.extension.cache', AppExtension::class)->tag('twig.extension'); - $services->set(CacheExtension::class)->tag('twig.extension'); - $services->set(FilesystemAdapter::class)->args([ - '$directory' => __DIR__ . '/../var/cache/twig_blocks' - ]); - $services->set('twig.runtime.cache', CacheRuntime::class)->args([new Reference(FilesystemAdapter::class)])->tag('twig.runtime'); + $services->set('twig.extension', AppExtension::class)->tag('twig.extension'); } protected function configureRoutes(RoutingConfigurator $routes): void diff --git a/src/Models/Product.php b/src/Models/Product.php index 139ddf9..3f5d456 100644 --- a/src/Models/Product.php +++ b/src/Models/Product.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; +use Illuminate\Support\Str; use function Symfony\Component\Clock\now; /** @@ -27,11 +28,13 @@ use function Symfony\Component\Clock\now; * @property float $productStandardPrice * @property float $lowestProductPrice30Days * @property Date $lastSeen + * @property integer $stock + * @property Object $promotions */ class Product extends Model { public $timestamps = true; - public $fillable = ['skuID']; + public $fillable = ['skuID', 'country_id']; public function country(): BelongsTo { @@ -57,9 +60,10 @@ class Product extends Model { return $this->hasOne(Price::class)->ofMany('price', 'MIN'); } + public function newestPrice(): HasOne { - return $this->hasOne(Price::class)->latest(); + return $this->hasOne(Price::class)->latest()->take(1); } public function stock(): HasMany @@ -69,7 +73,7 @@ class Product extends Model public function currentStock(): HasOne { - return $this->stock()->one()->ofMany()->withDefault(fn (Stock $stock) => $stock->stock = 0); + return $this->stock()->one()->ofMany()->withDefault(fn(Stock $stock) => $stock->stock = 0)->take(1); } public function toggleStarred(): self @@ -87,10 +91,23 @@ class Product extends Model ); } + public function promotions(): Attribute + { + return Attribute::make( + get: fn(?string $value) => json_decode($value ?? '{"hasPromotion": false}', 1), + set: function (\stdClass $value) { + $value->slug = Str::slug($value->tag); + + return json_encode($value); + } + ); + } + public function isDiscontinued(): bool { return $this->lastSeen < now()->format('Y-m-d'); } + public function isNew(): bool { return $this->created_at->format('Y-m-d') > now()->modify('-30 days')->format('Y-m-d'); diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php index 1a08554..22bc991 100644 --- a/src/Twig/AppExtension.php +++ b/src/Twig/AppExtension.php @@ -2,11 +2,11 @@ namespace Krzysiej\RyobiCrawler\Twig; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Krzysiej\RyobiCrawler\Models\Price; use Krzysiej\RyobiCrawler\Models\Product; use Krzysiej\RyobiCrawler\Models\Stock; +use Symfony\Component\Routing\RouterInterface; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; use Twig\TwigFunction; @@ -15,6 +15,10 @@ use function Symfony\Component\Clock\now; class AppExtension extends AbstractExtension { + public function __construct(public RouterInterface $route) + { + } + public function getFunctions(): array { return [ @@ -23,6 +27,7 @@ class AppExtension extends AbstractExtension new TwigFunction('newCount', [$this, 'newCount']), new TwigFunction('discontinuedCount', [$this, 'discontinuedCount']), new TwigFunction('lowestPriceCount', [$this, 'lowestPriceCount']), + new TwigFunction('renderCategoryTree', [$this, 'renderCategoryTree']), ]; } @@ -56,7 +61,7 @@ class AppExtension extends AbstractExtension public function lowestPriceCount(): int { return Product::whereRaw('priceCurrent = priceLowest') - ->whereRaw('lastSeen = "'.now()->format('Y-m-d').'"') + ->whereRaw('lastSeen = "' . now()->format('Y-m-d') . '"') ->whereRaw('priceCurrent < productStandardPrice') ->count(); } @@ -65,4 +70,28 @@ class AppExtension extends AbstractExtension { return $items->first(fn($item) => str_starts_with($item->created_at, $date)); } -} \ No newline at end of file + + public function renderCategoryTree($categories, $current, $level = 0): string + { + $tree = ''; + if ($level == 0) { + $tree .= ''; + } + return $tree; + + } +} diff --git a/templates/product.html.twig b/templates/product.html.twig index bbf3147..6444b01 100644 --- a/templates/product.html.twig +++ b/templates/product.html.twig @@ -1,28 +1,35 @@ {% extends "template.html.twig" %} {% block content %} -{% cache 'product' ~ product.id %}
+ href="{{ path('app_star', {'productId': product.id}) }}">{% if product.starred %}★{% else %} ☆ {% endif %} + - + + {% set stock = product.stock().get() %} {% for price in product.price %} - + {% endfor %}
{% if product.starred %}★{% else %} ☆ {% endif %} {{ product.name }} - {{ product.name }} - {{ product.subTitle }} + {{ product.name }} + {{ product.subTitle }} + {% if product.promotions is not null and product.promotions.hasPromotion %}PROMO: {{ product.promotions.tag }} + {% endif %} linklink
@@ -42,13 +49,14 @@ Stock
{{ price.price | format_currency(product.country.currency, {}, product.country.locale) }} {{ price.lowestProductPrice30Days | format_currency(product.country.currency, {}, product.country.locale) }} {{ price.productStandardPrice | format_currency(product.country.currency, {}, product.country.locale) }} {{ price.created_at }}{{ (product.stock | findByCreatedAtDate(price.created_at | slice(0,10))).stock ?? '' }}{{ (stock | findByCreatedAtDate(price.created_at | slice(0,10))).stock ?? '' }}
@@ -131,6 +139,5 @@ } }); -{% endcache %} {% endblock %} diff --git a/templates/productList.html.twig b/templates/productList.html.twig index 2d17007..2945194 100644 --- a/templates/productList.html.twig +++ b/templates/productList.html.twig @@ -1,70 +1,94 @@ {% extends "template.html.twig" %} {% block content %} -{% cache 'list_' ~ listType %} -
- - - - - - - - - - - - - - {% for product in products %} - - - - - - - - {% endif %} + {% if listType starts with 'category_' %} + {{ renderCategoryTree(categoryTree, category) | raw }} + {% endif %} - - - - {% endfor %} -
NameCategoriesLowest PriceCurrent Price
{% if product.starred == true %}★{% else %} ☆ {% endif %}{{ product.name }} - {{ product.name }} - {% if product.currentStock.stock > 0 %} - stock: {{ product.currentStock.stock }} - {% else %} - out of stock - {% endif %} - {% if product.isDiscontinued() %} - is discontinued - {% endif %} - {% if product.isNew() %} - is new - {% endif %} - {{ product.subTitle }} - - - link - {% if product.isDiscontinued() or product.priceCurrent == product.productStandardPrice %} - {{ product.priceLowest | format_currency(product.country.currency, {}, product.country.locale) }} - {% else %} - {% if product.priceLowest != product.priceCurrent %}{{ product.priceLowest | format_currency(product.country.currency, {}, product.country.locale) }}{%else%}now lowest{% endif %}{{ product.priceCurrent | format_currency(product.country.currency, {}, product.country.locale) }} -
- {% if product.priceCurrent != product.productStandardPrice %}{{ product.productStandardPrice | format_currency(product.country.currency, {}, product.country.locale) }} {{ ((1 - product.priceCurrent / product.productStandardPrice)*100)|number_format(0) }}% - {% endif %} -
-
-
-{% endcache %} + {% if listType starts with 'promos' %} + {% for promo in promos %} + PROMO: {{ promo.tag }} + {% endfor %} + {% endif %} + + + {% if (listType starts with 'category_' and category == null) or not (listType starts with 'category_') or (listType starts with 'category_' and category is not null) %} +
+ + + + + + + + + + + + + + {% for product in products %} + + + + + + + + {% endif %} + + + + + {% endfor %} +
NameCategoriesLowest PriceCurrent Price
{% if product.starred == true %}★{% else %} ☆ {% endif %} + {{ product.name }} + {{ product.name }} + {% if product.stock > 0 %} + stock: {{ product.stock }} + {% else %} + out of stock + {% endif %} + {% if product.isDiscontinued() %} + is discontinued + {% endif %} + {% if product.isNew() %} + is new + {% endif %} + {{ product.subTitle }} + {% if product.promotions is not null and product.promotions.hasPromotion %}PROMO: {{ product.promotions.tag }}{% endif %} + + + link + {% if product.isDiscontinued() or product.priceCurrent == product.productStandardPrice %} + {{ product.priceLowest | format_currency(product.country.currency, {}, product.country.locale) }} + {% else %} + {% if product.priceLowest != product.priceCurrent %}{{ product.priceLowest | format_currency(product.country.currency, {}, product.country.locale) }}{% else %} + now lowest{% endif %}{{ product.priceCurrent | format_currency(product.country.currency, {}, product.country.locale) }} +
+ {% if product.priceCurrent != product.productStandardPrice %}{{ product.productStandardPrice | format_currency(product.country.currency, {}, product.country.locale) }} + {{ ((1 - product.priceCurrent / product.productStandardPrice)*100)|number_format(0) }}% + {% endif %} +
+
+
+ {% endif %} {% endblock %} diff --git a/templates/template.html.twig b/templates/template.html.twig index da00920..875b5b9 100644 --- a/templates/template.html.twig +++ b/templates/template.html.twig @@ -1,5 +1,5 @@ - + @@ -18,7 +18,6 @@