From 28416364ea6ac87598ea7d1f477e0f684fb1ec39 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Wed, 25 Feb 2026 12:15:03 +0100 Subject: [PATCH 01/51] add cs-fixer & fix files, add phpstan & begin lvl 0 --- backup/index.php | 1 + backup/override/index.php | 1 + classes/controllers/LengowController.php | 1 + .../controllers/LengowDashboardController.php | 1 + classes/controllers/LengowFeedController.php | 1 + classes/controllers/LengowHelpController.php | 1 + classes/controllers/LengowHomeController.php | 1 + .../controllers/LengowLegalsController.php | 1 + .../LengowMainSettingController.php | 1 + classes/controllers/LengowOrderController.php | 1 + .../LengowOrderSettingController.php | 1 + .../controllers/LengowToolboxController.php | 1 + classes/controllers/index.php | 1 + classes/index.php | 1 + classes/models/LengowAction.php | 1 + classes/models/LengowAddress.php | 1 + classes/models/LengowBackup.php | 1 + classes/models/LengowCarrier.php | 1 + classes/models/LengowCart.php | 3 +- classes/models/LengowCatalog.php | 1 + classes/models/LengowConfiguration.php | 1 + classes/models/LengowConfigurationForm.php | 1 + classes/models/LengowConnector.php | 1 + classes/models/LengowCountry.php | 1 + classes/models/LengowCustomer.php | 1 + classes/models/LengowException.php | 1 + classes/models/LengowExport.php | 1 + classes/models/LengowFeed.php | 1 + classes/models/LengowFile.php | 1 + classes/models/LengowGender.php | 1 + classes/models/LengowHook.php | 3 +- classes/models/LengowImport.php | 20 +- classes/models/LengowImportOrder.php | 1 + classes/models/LengowInstall.php | 7 +- classes/models/LengowLink.php | 1 + classes/models/LengowList.php | 1 + classes/models/LengowLog.php | 1 + classes/models/LengowMain.php | 1 + classes/models/LengowMarketplace.php | 3 +- classes/models/LengowMethod.php | 3 +- classes/models/LengowNameParser.php | 1 + classes/models/LengowOrder.php | 3 +- classes/models/LengowOrderCarrier.php | 1 + classes/models/LengowOrderDetail.php | 1 + classes/models/LengowOrderError.php | 1 + classes/models/LengowOrderLine.php | 1 + classes/models/LengowPaymentModule.php | 1 + classes/models/LengowProduct.php | 1 + classes/models/LengowShop.php | 1 + classes/models/LengowSync.php | 1 + classes/models/LengowToolbox.php | 1 + classes/models/LengowToolboxElement.php | 1 + classes/models/LengowTranslation.php | 1 + classes/models/index.php | 1 + composer.json | 10 +- composer.lock | 2799 ++++++++++++++++- config/index.php | 1 + .../admin/AdminLengowDashboardController.php | 1 + .../admin/AdminLengowFeedController.php | 1 + .../admin/AdminLengowHelpController.php | 1 + .../admin/AdminLengowHomeController.php | 1 + .../admin/AdminLengowLegalsController.php | 1 + .../AdminLengowMainSettingController.php | 1 + .../admin/AdminLengowOrderController.php | 1 + .../AdminLengowOrderSettingController.php | 1 + .../admin/AdminLengowToolboxController.php | 1 + controllers/admin/index.php | 1 + controllers/index.php | 1 + es.php | 1 + export/index.php | 1 + fr.php | 1 + index.php | 1 + it.php | 1 + lengow.php | 6 +- loader.php | 1 + logs/index.php | 1 + mails/de/index.php | 1 + mails/en/index.php | 1 + mails/es/index.php | 1 + mails/fr/index.php | 1 + mails/gb/index.php | 1 + mails/index.php | 1 + mails/it/index.php | 1 + mails/nl/index.php | 1 + mails/pt/index.php | 1 + mails/sv/index.php | 1 + src/Controller/AdminOrderController.php | 4 +- src/Controller/index.php | 1 + src/index.php | 1 + tests/phpstan/phpstan.neon | 9 + translations/index.php | 1 + translations/yml/index.php | 1 + upgrade/index.php | 1 + upgrade/update_3.0.0.php | 1 + upgrade/update_3.0.1.php | 1 + upgrade/update_3.0.2.php | 1 + upgrade/update_3.2.2.php | 1 + upgrade/update_3.2.3.php | 1 + upgrade/update_3.7.0.php | 1 + upgrade/update_3.7.1.php | 1 + .../Order/Order/Blocks/View/Modal/index.php | 1 + .../Sell/Order/Order/Blocks/View/index.php | 1 + .../Admin/Sell/Order/Order/Blocks/index.php | 1 + .../Admin/Sell/Order/Order/index.php | 1 + views/PrestaShop/Admin/Sell/Order/index.php | 1 + views/PrestaShop/Admin/Sell/index.php | 1 + views/PrestaShop/Admin/index.php | 1 + views/PrestaShop/index.php | 1 + views/css/index.php | 1 + views/fonts/index.php | 1 + views/img/flag/index.php | 1 + views/img/index.php | 1 + views/index.php | 1 + views/js/index.php | 1 + views/js/lengow/index.php | 1 + views/templates/admin/index.php | 1 + .../admin/lengow_dashboard/helpers/index.php | 1 + .../lengow_dashboard/helpers/view/index.php | 1 + .../admin/lengow_dashboard/index.php | 1 + .../admin/lengow_feed/helpers/index.php | 1 + .../admin/lengow_feed/helpers/view/index.php | 1 + views/templates/admin/lengow_feed/index.php | 1 + .../admin/lengow_help/helpers/index.php | 1 + .../admin/lengow_help/helpers/view/index.php | 1 + views/templates/admin/lengow_help/index.php | 1 + .../admin/lengow_home/helpers/index.php | 1 + .../admin/lengow_home/helpers/view/index.php | 1 + views/templates/admin/lengow_home/index.php | 1 + .../admin/lengow_legals/helpers/index.php | 1 + .../lengow_legals/helpers/view/index.php | 1 + views/templates/admin/lengow_legals/index.php | 1 + .../lengow_main_setting/helpers/index.php | 1 + .../helpers/view/index.php | 1 + .../admin/lengow_main_setting/index.php | 1 + .../admin/lengow_order/helpers/index.php | 1 + .../admin/lengow_order/helpers/view/index.php | 1 + views/templates/admin/lengow_order/index.php | 1 + .../lengow_order_setting/helpers/index.php | 1 + .../helpers/view/index.php | 1 + .../admin/lengow_order_setting/index.php | 1 + .../admin/lengow_toolbox/helpers/index.php | 1 + .../lengow_toolbox/helpers/view/index.php | 1 + .../templates/admin/lengow_toolbox/index.php | 1 + views/templates/admin/order/index.php | 1 + views/templates/front/index.php | 1 + views/templates/hook/index.php | 1 + views/templates/hook/order/index.php | 1 + views/templates/index.php | 1 + webservice/cron.php | 1 + webservice/export.php | 1 + webservice/index.php | 1 + webservice/toolbox.php | 1 + 152 files changed, 2979 insertions(+), 31 deletions(-) create mode 100644 tests/phpstan/phpstan.neon diff --git a/backup/index.php b/backup/index.php index cbb2c701..08fc27c4 100755 --- a/backup/index.php +++ b/backup/index.php @@ -1,4 +1,5 @@ shop; diff --git a/classes/models/LengowCatalog.php b/classes/models/LengowCatalog.php index 8e5132e6..9fd49a4b 100644 --- a/classes/models/LengowCatalog.php +++ b/classes/models/LengowCatalog.php @@ -1,4 +1,5 @@ '1.6', // version 8.0 'displayHome' => '8.0', - 'actionOrderStatusPostUpdate' => '8.0' + 'actionOrderStatusPostUpdate' => '8.0', ]; foreach ($lengowHooks as $hook => $version) { if ((float) $version <= (float) Tools::substr(_PS_VERSION_, 0, 3)) { diff --git a/classes/models/LengowImport.php b/classes/models/LengowImport.php index 1eca203f..1380c7c3 100755 --- a/classes/models/LengowImport.php +++ b/classes/models/LengowImport.php @@ -1,4 +1,5 @@ self::MAX_INTERVAL_TIME ? self::MAX_INTERVAL_TIME : $intervalTime; - } - elseif ($days) { + } elseif ($days) { $intervalTime = floor($days * self::MIN_INTERVAL_TIME); // convert days to seconds $intervalTime = $intervalTime > self::MAX_INTERVAL_TIME ? self::MAX_INTERVAL_TIME : $intervalTime; } else { @@ -1169,22 +1169,21 @@ private static function setEnd() /** * Acquire a named lock * - * @param string $lockName Name of the lock - * @param int $timeout Timeout in seconds + * @param string $lockName Name of the lock + * @param int $timeout Timeout in seconds * * @return bool True if the lock was acquired, false otherwise */ private function acquireLock(string $lockName, int $timeout = 0): bool { try { - $db = \Db::getInstance(); + $db = Db::getInstance(); $result = $db->getValue( 'SELECT GET_LOCK("' . pSQL($lockName) . '", ' . (int) $timeout . ')' ); return (bool) $result; - - } catch (\Exception $e) { + } catch (Exception $e) { LengowMain::log( LengowLog::CODE_IMPORT, LengowMain::setLogMessage( @@ -1201,21 +1200,20 @@ private function acquireLock(string $lockName, int $timeout = 0): bool /** * Release a named lock * - * @param string $lockName Name of the lock + * @param string $lockName Name of the lock * * @return bool True if the lock was released, false otherwise */ private function releaseLock(string $lockName): bool { try { - $db = \Db::getInstance(); + $db = Db::getInstance(); $result = $db->getValue( 'SELECT RELEASE_LOCK("' . pSQL($lockName) . '")' ); return (bool) $result; - - } catch (\Exception $e) { + } catch (Exception $e) { LengowMain::log( LengowLog::CODE_IMPORT, LengowMain::setLogMessage( diff --git a/classes/models/LengowImportOrder.php b/classes/models/LengowImportOrder.php index 9e10eb72..986c83ce 100755 --- a/classes/models/LengowImportOrder.php +++ b/classes/models/LengowImportOrder.php @@ -1,4 +1,5 @@ $this->lengowModule->version]) ); - return true; } @@ -243,7 +243,6 @@ public function clearCaches() LengowLog::CODE_INSTALL, LengowMain::setLogMessage('log.install.clear_cache_success') ); - } catch (Exception $e) { LengowMain::log( LengowLog::CODE_INSTALL, @@ -1116,8 +1115,8 @@ private function saveOverride() } /** - * Create Lengow customer group if not exists - */ + * Create Lengow customer group if not exists + */ private function createLengowCustomerGroup() { $marketplaceGroupId = null; diff --git a/classes/models/LengowLink.php b/classes/models/LengowLink.php index e84fb607..81ff116d 100755 --- a/classes/models/LengowLink.php +++ b/classes/models/LengowLink.php @@ -1,4 +1,5 @@ checkAction($action); if (!in_array($lengowOrder->lengowState, $this->getRefundStatuses(), true)) { diff --git a/classes/models/LengowMethod.php b/classes/models/LengowMethod.php index cb8a34a9..1ddef923 100755 --- a/classes/models/LengowMethod.php +++ b/classes/models/LengowMethod.php @@ -1,4 +1,5 @@ =8.1" + }, "autoload": { "psr-4": { "Lengow\\": "src/" @@ -12,5 +15,10 @@ "classes/" ] }, - "type": "prestashop-module" + "type": "prestashop-module", + "require-dev": { + "prestashop/php-dev-tools": "^5.0", + "friendsofphp/php-cs-fixer": "^3.94", + "phpstan/phpstan": "^2.1" + } } diff --git a/composer.lock b/composer.lock index 24ef0089..b47958e0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,15 +4,2802 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6643397d4ae64e38ae5518f118d46b6d", + "content-hash": "da5260d8b99d92781c6a81ea58bb1535", "packages": [], - "packages-dev": [], + "packages-dev": [ + { + "name": "clue/ndjson-react", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\React\\NDJson\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", + "keywords": [ + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" + ], + "support": { + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-12-23T10:58:28+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.4", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.4" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + } + ], + "time": "2025-08-20T19:15:30+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2025-08-14T07:29:31+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.94.2", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7787ceff91365ba7d623ec410b8f429cdebb4f63", + "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63", + "shasum": "" + }, + "require": { + "clue/ndjson-react": "^1.3", + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.5", + "ext-filter": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "fidry/cpu-core-counter": "^1.3", + "php": "^7.4 || ^8.0", + "react/child-process": "^0.6.6", + "react/event-loop": "^1.5", + "react/socket": "^1.16", + "react/stream": "^1.4", + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.33", + "symfony/polyfill-php80": "^1.33", + "symfony/polyfill-php81": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3.1 || ^2.7.1", + "infection/infection": "^0.32.3", + "justinrainbow/json-schema": "^6.6.4", + "keradus/cli-executor": "^2.3", + "mikey179/vfsstream": "^1.6.12", + "php-coveralls/php-coveralls": "^2.9.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7", + "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51", + "symfony/polyfill-php85": "^1.33", + "symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4", + "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "exclude-from-classmap": [ + "src/**/Internal/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "keywords": [ + "Static code analysis", + "fixer", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.2" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2026-02-20T16:13:53+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.40", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b", + "reference": "9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2026-02-23T15:04:35+00:00" + }, + { + "name": "prestashop/php-dev-tools", + "version": "v5", + "source": { + "type": "git", + "url": "https://github.com/PrestaShop/php-dev-tools.git", + "reference": "4b284d9b07a274505c81144536924eb4014e6fbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PrestaShop/php-dev-tools/zipball/4b284d9b07a274505c81144536924eb4014e6fbf", + "reference": "4b284d9b07a274505c81144536924eb4014e6fbf", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/console": "~3.2 || ~4.0 || ~5.0 || ~6.0 || ~7.0", + "symfony/filesystem": "~3.2 || ~4.0 || ~5.0 || ~6.0 || ~7.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2" + }, + "suggest": { + "phpstan/phpstan": "^0.12", + "prestashop/autoindex": "^2.0", + "prestashop/header-stamp": "^2.0", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/prestashop-coding-standards" + ], + "type": "library", + "autoload": { + "psr-4": { + "PrestaShop\\CodingStandards\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PrestaShop" + } + ], + "description": "PrestaShop coding standards", + "support": { + "issues": "https://github.com/PrestaShop/php-dev-tools/issues", + "source": "https://github.com/PrestaShop/php-dev-tools/tree/v5" + }, + "time": "2024-05-23T12:27:45+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+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/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "react/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, Promise-based cache interface for ReactPHP", + "keywords": [ + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/child-process", + "version": "v0.6.7", + "source": { + "type": "git", + "url": "https://github.com/reactphp/child-process.git", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/event-loop": "^1.2", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/socket": "^1.16", + "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\ChildProcess\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven library for executing child processes with ReactPHP.", + "keywords": [ + "event-driven", + "process", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/child-process/issues", + "source": "https://github.com/reactphp/child-process/tree/v0.6.7" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-12-23T15:25:20+00:00" + }, + { + "name": "react/dns", + "version": "v1.14.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3 || ^2", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.14.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-11-18T19:34:28+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-11-17T20:46:25+00:00" + }, + { + "name": "react/promise", + "version": "v3.3.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.12.28 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.3.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-08-19T18:57:03+00:00" + }, + { + "name": "react/socket", + "version": "v1.17.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.13", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3.3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.17.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-11-19T20:47:34+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/a2b6d09d7729ee87d605a439469f9dcc39be5ea3", + "reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0", + "symfony/process": "^7.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/diff", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:42:27+00:00" + }, + { + "name": "symfony/console", + "version": "v7.4.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/41e38717ac1dd7a46b6bda7d6a82af2d98a78894", + "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "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" + }, + "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" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "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/v7.4.4" + }, + "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": "2026-01-13T11:36:38+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.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": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v8.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99301401da182b6cfaa4700dbe9987bb75474b47", + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/security-http": "<7.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "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": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "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/v8.0.4" + }, + "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": "2026-01-05T11:45:55+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "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": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "d551b38811096d0be9c4691d406991b47c0c630a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a", + "reference": "d551b38811096d0be9c4691d406991b47c0c630a", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.4.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-11-27T13:27:24+00:00" + }, + { + "name": "symfony/finder", + "version": "v8.0.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/8bd576e97c67d45941365bf824e18dc8538e6eb0", + "reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "symfony/filesystem": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v8.0.5" + }, + "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": "2026-01-26T15:08:38+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v8.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d2b592535ffa6600c265a3893a7f7fd2bad82dd7", + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v8.0.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-11-12T15:55:31+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "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.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-06-27T09:58:17+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/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": "2024-12-23T08:48:59+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "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\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/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-01-02T08:10:11+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "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\\Php81\\": "" + }, + "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.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php84", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "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\\Php84\\": "" + }, + "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.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/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-06-24T13:30:11+00:00" + }, + { + "name": "symfony/process", + "version": "v8.0.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", + "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v8.0.5" + }, + "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": "2026-01-26T15:08:38+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + }, + "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-15T11:30:57+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v8.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/67df1914c6ccd2d7b52f70d40cf2aea02159d942", + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v8.0.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-08-04T07:36:47+00:00" + }, + { + "name": "symfony/string", + "version": "v8.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "758b372d6882506821ed666032e43020c4f57194" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/758b372d6882506821ed666032e43020c4f57194", + "reference": "758b372d6882506821ed666032e43020c4f57194", + "shasum": "" + }, + "require": { + "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.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": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "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/v8.0.4" + }, + "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": "2026-01-12T12:37:40+00:00" + } + ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.2.0" + "platform": { + "php": ">=8.1" + }, + "platform-dev": {}, + "plugin-api-version": "2.9.0" } diff --git a/config/index.php b/config/index.php index cbb2c701..08fc27c4 100644 --- a/config/index.php +++ b/config/index.php @@ -1,4 +1,5 @@ module_key = '__LENGOW_PRESTASHOP_PRODUCT_KEY__'; $this->ps_versions_compliancy = [ 'min' => '1.7.8', - 'max' => '8.99.99', + 'max' => '9.99.99', ]; $this->bootstrap = true; @@ -152,6 +153,7 @@ public function hookDisplayBackOfficeHeader() /** * Hook on Home page + * * @depercated Use hookDisplayHome instead */ public function hookHome() @@ -211,7 +213,7 @@ public function hookActionOrderStatusUpdate($args) */ public function hookActionOrderStatusPostUpdate($args) { - $this->hookClass->hookActionOrderStatusPostUpdate($args); + $this->hookClass->hookActionOrderStatusPostUpdate($args); } /** diff --git a/loader.php b/loader.php index 1aa6ae4c..c5e74133 100644 --- a/loader.php +++ b/loader.php @@ -1,4 +1,5 @@ addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages($e))); } - } else { - // exit ('form not valid'); } + // exit ('form not valid'); return $this->redirectToRoute('admin_orders_view', [ 'orderId' => $orderId, diff --git a/src/Controller/index.php b/src/Controller/index.php index cbb2c701..08fc27c4 100755 --- a/src/Controller/index.php +++ b/src/Controller/index.php @@ -1,4 +1,5 @@ Date: Thu, 26 Feb 2026 10:25:56 +0100 Subject: [PATCH 02/51] remove dev dependencies breaking prestashop --- composer.json | 7 +- composer.lock | 2789 +----------------------------------- tests/phpstan/phpstan.neon | 5 +- 3 files changed, 6 insertions(+), 2795 deletions(-) diff --git a/composer.json b/composer.json index 2f39f78d..c603eeac 100644 --- a/composer.json +++ b/composer.json @@ -15,10 +15,5 @@ "classes/" ] }, - "type": "prestashop-module", - "require-dev": { - "prestashop/php-dev-tools": "^5.0", - "friendsofphp/php-cs-fixer": "^3.94", - "phpstan/phpstan": "^2.1" - } + "type": "prestashop-module" } diff --git a/composer.lock b/composer.lock index b47958e0..eb1a28a1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,2794 +4,9 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "da5260d8b99d92781c6a81ea58bb1535", + "content-hash": "7c34a031ca70c4216dadaf1ad788f169", "packages": [], - "packages-dev": [ - { - "name": "clue/ndjson-react", - "version": "v1.3.0", - "source": { - "type": "git", - "url": "https://github.com/clue/reactphp-ndjson.git", - "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", - "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", - "shasum": "" - }, - "require": { - "php": ">=5.3", - "react/stream": "^1.2" - }, - "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", - "react/event-loop": "^1.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Clue\\React\\NDJson\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering" - } - ], - "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", - "homepage": "https://github.com/clue/reactphp-ndjson", - "keywords": [ - "NDJSON", - "json", - "jsonlines", - "newline", - "reactphp", - "streaming" - ], - "support": { - "issues": "https://github.com/clue/reactphp-ndjson/issues", - "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" - }, - "funding": [ - { - "url": "https://clue.engineering/support", - "type": "custom" - }, - { - "url": "https://github.com/clue", - "type": "github" - } - ], - "time": "2022-12-23T10:58:28+00:00" - }, - { - "name": "composer/pcre", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<1.11.10" - }, - "require-dev": { - "phpstan/phpstan": "^1.12 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8 || ^9" - }, - "type": "library", - "extra": { - "phpstan": { - "includes": [ - "extension.neon" - ] - }, - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-11-12T16:29:46+00:00" - }, - { - "name": "composer/semver", - "version": "3.4.4", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.11", - "symfony/phpunit-bridge": "^3 || ^7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.4" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - } - ], - "time": "2025-08-20T19:15:30+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.5", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-05-06T16:37:16+00:00" - }, - { - "name": "evenement/evenement", - "version": "v3.0.2", - "source": { - "type": "git", - "url": "https://github.com/igorw/evenement.git", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", - "shasum": "" - }, - "require": { - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "^9 || ^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Evenement\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - } - ], - "description": "Événement is a very simple event dispatching library for PHP", - "keywords": [ - "event-dispatcher", - "event-emitter" - ], - "support": { - "issues": "https://github.com/igorw/evenement/issues", - "source": "https://github.com/igorw/evenement/tree/v3.0.2" - }, - "time": "2023-08-08T05:53:35+00:00" - }, - { - "name": "fidry/cpu-core-counter", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "fidry/makefile": "^0.2.0", - "fidry/php-cs-fixer-config": "^1.1.2", - "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-deprecation-rules": "^2.0.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^8.5.31 || ^9.5.26", - "webmozarts/strict-phpunit": "^7.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Fidry\\CpuCoreCounter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com" - } - ], - "description": "Tiny utility to get the number of CPU cores.", - "keywords": [ - "CPU", - "core" - ], - "support": { - "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" - }, - "funding": [ - { - "url": "https://github.com/theofidry", - "type": "github" - } - ], - "time": "2025-08-14T07:29:31+00:00" - }, - { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.94.2", - "source": { - "type": "git", - "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7787ceff91365ba7d623ec410b8f429cdebb4f63", - "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63", - "shasum": "" - }, - "require": { - "clue/ndjson-react": "^1.3", - "composer/semver": "^3.4", - "composer/xdebug-handler": "^3.0.5", - "ext-filter": "*", - "ext-hash": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.3", - "php": "^7.4 || ^8.0", - "react/child-process": "^0.6.6", - "react/event-loop": "^1.5", - "react/socket": "^1.16", - "react/stream": "^1.4", - "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0", - "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/polyfill-mbstring": "^1.33", - "symfony/polyfill-php80": "^1.33", - "symfony/polyfill-php81": "^1.33", - "symfony/polyfill-php84": "^1.33", - "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", - "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" - }, - "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.7.1", - "infection/infection": "^0.32.3", - "justinrainbow/json-schema": "^6.6.4", - "keradus/cli-executor": "^2.3", - "mikey179/vfsstream": "^1.6.12", - "php-coveralls/php-coveralls": "^2.9.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7", - "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51", - "symfony/polyfill-php85": "^1.33", - "symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4", - "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1" - }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters." - }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", - "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - }, - "exclude-from-classmap": [ - "src/**/Internal/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - } - ], - "description": "A tool to automatically fix PHP code style", - "keywords": [ - "Static code analysis", - "fixer", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.2" - }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } - ], - "time": "2026-02-20T16:13:53+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "2.1.40", - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b", - "reference": "9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b", - "shasum": "" - }, - "require": { - "php": "^7.4|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - } - ], - "time": "2026-02-23T15:04:35+00:00" - }, - { - "name": "prestashop/php-dev-tools", - "version": "v5", - "source": { - "type": "git", - "url": "https://github.com/PrestaShop/php-dev-tools.git", - "reference": "4b284d9b07a274505c81144536924eb4014e6fbf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PrestaShop/php-dev-tools/zipball/4b284d9b07a274505c81144536924eb4014e6fbf", - "reference": "4b284d9b07a274505c81144536924eb4014e6fbf", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/console": "~3.2 || ~4.0 || ~5.0 || ~6.0 || ~7.0", - "symfony/filesystem": "~3.2 || ~4.0 || ~5.0 || ~6.0 || ~7.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.2" - }, - "suggest": { - "phpstan/phpstan": "^0.12", - "prestashop/autoindex": "^2.0", - "prestashop/header-stamp": "^2.0", - "squizlabs/php_codesniffer": "^3.4" - }, - "bin": [ - "bin/prestashop-coding-standards" - ], - "type": "library", - "autoload": { - "psr-4": { - "PrestaShop\\CodingStandards\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PrestaShop" - } - ], - "description": "PrestaShop coding standards", - "support": { - "issues": "https://github.com/PrestaShop/php-dev-tools/issues", - "source": "https://github.com/PrestaShop/php-dev-tools/tree/v5" - }, - "time": "2024-05-23T12:27:45+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+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/log", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" - }, - { - "name": "react/cache", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/cache.git", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "react/promise": "^3.0 || ^2.0 || ^1.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async, Promise-based cache interface for ReactPHP", - "keywords": [ - "cache", - "caching", - "promise", - "reactphp" - ], - "support": { - "issues": "https://github.com/reactphp/cache/issues", - "source": "https://github.com/reactphp/cache/tree/v1.2.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2022-11-30T15:59:55+00:00" - }, - { - "name": "react/child-process", - "version": "v0.6.7", - "source": { - "type": "git", - "url": "https://github.com/reactphp/child-process.git", - "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", - "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", - "shasum": "" - }, - "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.0", - "react/event-loop": "^1.2", - "react/stream": "^1.4" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/socket": "^1.16", - "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\ChildProcess\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Event-driven library for executing child processes with ReactPHP.", - "keywords": [ - "event-driven", - "process", - "reactphp" - ], - "support": { - "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.7" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-12-23T15:25:20+00:00" - }, - { - "name": "react/dns", - "version": "v1.14.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/dns.git", - "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", - "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "react/cache": "^1.0 || ^0.6 || ^0.5", - "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.7 || ^1.2.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3 || ^2", - "react/promise-timer": "^1.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\Dns\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async DNS resolver for ReactPHP", - "keywords": [ - "async", - "dns", - "dns-resolver", - "reactphp" - ], - "support": { - "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.14.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-11-18T19:34:28+00:00" - }, - { - "name": "react/event-loop", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/event-loop.git", - "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", - "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" - }, - "suggest": { - "ext-pcntl": "For signal handling support when using the StreamSelectLoop" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\EventLoop\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", - "keywords": [ - "asynchronous", - "event-loop" - ], - "support": { - "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-11-17T20:46:25+00:00" - }, - { - "name": "react/promise", - "version": "v3.3.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", - "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", - "shasum": "" - }, - "require": { - "php": ">=7.1.0" - }, - "require-dev": { - "phpstan/phpstan": "1.12.28 || 1.4.10", - "phpunit/phpunit": "^9.6 || ^7.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "React\\Promise\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "keywords": [ - "promise", - "promises" - ], - "support": { - "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v3.3.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-08-19T18:57:03+00:00" - }, - { - "name": "react/socket", - "version": "v1.17.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/socket.git", - "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", - "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", - "shasum": "" - }, - "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.0", - "react/dns": "^1.13", - "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.6 || ^1.2.1", - "react/stream": "^1.4" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3.3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\Socket\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", - "keywords": [ - "Connection", - "Socket", - "async", - "reactphp", - "stream" - ], - "support": { - "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.17.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-11-19T20:47:34+00:00" - }, - { - "name": "react/stream", - "version": "v1.4.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/stream.git", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", - "shasum": "" - }, - "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.8", - "react/event-loop": "^1.2" - }, - "require-dev": { - "clue/stream-filter": "~1.2", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\Stream\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", - "keywords": [ - "event-driven", - "io", - "non-blocking", - "pipe", - "reactphp", - "readable", - "stream", - "writable" - ], - "support": { - "issues": "https://github.com/reactphp/stream/issues", - "source": "https://github.com/reactphp/stream/tree/v1.4.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2024-06-11T12:45:25+00:00" - }, - { - "name": "sebastian/diff", - "version": "8.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/a2b6d09d7729ee87d605a439469f9dcc39be5ea3", - "reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "phpunit/phpunit": "^13.0", - "symfony/process": "^7.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "8.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/8.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/diff", - "type": "tidelift" - } - ], - "time": "2026-02-06T04:42:27+00:00" - }, - { - "name": "symfony/console", - "version": "v7.4.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/41e38717ac1dd7a46b6bda7d6a82af2d98a78894", - "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "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" - }, - "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" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "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/v7.4.4" - }, - "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": "2026-01-13T11:36:38+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "files": [ - "function.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": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v8.0.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "99301401da182b6cfaa4700dbe9987bb75474b47" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99301401da182b6cfaa4700dbe9987bb75474b47", - "reference": "99301401da182b6cfaa4700dbe9987bb75474b47", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "symfony/event-dispatcher-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/security-http": "<7.4", - "symfony/service-contracts": "<2.5" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "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": "^7.4|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "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/v8.0.4" - }, - "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": "2026-01-05T11:45:55+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v3.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/event-dispatcher": "^1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "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": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v7.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^6.4|^7.0|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.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-11-27T13:27:24+00:00" - }, - { - "name": "symfony/finder", - "version": "v8.0.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8bd576e97c67d45941365bf824e18dc8538e6eb0", - "reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "require-dev": { - "symfony/filesystem": "^7.4|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v8.0.5" - }, - "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": "2026-01-26T15:08:38+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v8.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d2b592535ffa6600c265a3893a7f7fd2bad82dd7", - "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v8.0.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-11-12T15:55:31+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/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": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "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.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-06-27T09:58:17+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.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": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/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": "2024-12-23T08:48:59+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "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\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/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-01-02T08:10:11+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "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\\Php81\\": "" - }, - "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.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/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": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-php84", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", - "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\\Php84\\": "" - }, - "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.4+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php84/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-06-24T13:30:11+00:00" - }, - { - "name": "symfony/process", - "version": "v8.0.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", - "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", - "shasum": "" - }, - "require": { - "php": ">=8.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v8.0.5" - }, - "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": "2026-01-26T15:08:38+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.6.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "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": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" - }, - "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-15T11:30:57+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v8.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/67df1914c6ccd2d7b52f70d40cf2aea02159d942", - "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "symfony/service-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v8.0.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-08-04T07:36:47+00:00" - }, - { - "name": "symfony/string", - "version": "v8.0.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "758b372d6882506821ed666032e43020c4f57194" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/758b372d6882506821ed666032e43020c4f57194", - "reference": "758b372d6882506821ed666032e43020c4f57194", - "shasum": "" - }, - "require": { - "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.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": "^7.4|^8.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "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/v8.0.4" - }, - "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": "2026-01-12T12:37:40+00:00" - } - ], + "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": {}, diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon index 3ab7b0bb..64d73ec3 100644 --- a/tests/phpstan/phpstan.neon +++ b/tests/phpstan/phpstan.neon @@ -1,6 +1,7 @@ -includes: - - %currentWorkingDirectory%/vendor/prestashop/php-dev-tools/phpstan/ps-module-extension.neon +# _PS_ROOT_DIR_=~/prestashop/root PS_DEV_TOOLS_DIR=~/.config/composer/vendor/prestashop/php-dev-tools phpstan analyse --configuration=tests/phpstan/phpstan.neon +includes: + - %env.PS_DEV_TOOLS_DIR%/phpstan/ps-module-extension.neon parameters: level: 0 paths: From 9aef3b8e34ae9003a2b341fad4d8f2dc3184fd9a Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Thu, 26 Feb 2026 15:03:07 +0100 Subject: [PATCH 03/51] fix some Tools functions & product page --- classes/controllers/LengowController.php | 2 +- classes/models/LengowAddress.php | 8 +- classes/models/LengowCarrier.php | 2 +- classes/models/LengowCart.php | 85 +++++++++++++++++++-- classes/models/LengowConnector.php | 4 +- classes/models/LengowCustomer.php | 2 +- classes/models/LengowExport.php | 4 +- classes/models/LengowFeed.php | 2 +- classes/models/LengowList.php | 43 +++++++++-- classes/models/LengowMain.php | 10 +-- classes/models/LengowMethod.php | 6 +- classes/models/LengowProduct.php | 2 +- classes/models/LengowTranslation.php | 2 +- src/Controller/AdminOrderController.php | 94 +++++++++++++++++------- 14 files changed, 203 insertions(+), 63 deletions(-) diff --git a/classes/controllers/LengowController.php b/classes/controllers/LengowController.php index 9ce23321..470118af 100755 --- a/classes/controllers/LengowController.php +++ b/classes/controllers/LengowController.php @@ -93,7 +93,7 @@ public function forceDisplay() $module = Module::getInstanceByName('lengow'); $lengowMain = new LengowMain(); $className = get_class($this); - $path = $lengowMain->fromCamelCase(Tools::substr($className, 0, Tools::strlen($className) - 10)); + $path = $lengowMain->fromCamelCase(Tools::substr($className, 0, mb_strlen($className) - 10)); $this->prepareDisplay(); echo $module->display(_PS_MODULE_LENGOW_DIR_, 'views/templates/admin/' . $path . '/helpers/view/view.tpl'); } diff --git a/classes/models/LengowAddress.php b/classes/models/LengowAddress.php index 0cb767a5..32634b7d 100755 --- a/classes/models/LengowAddress.php +++ b/classes/models/LengowAddress.php @@ -546,7 +546,7 @@ public function validateLengow() ) { $this->validateFieldLengow($fieldName, self::LENGOW_EMPTY_ERROR); } - if (isset($constraints['size']) && Tools::strlen($this->{$fieldName}) > $constraints['size']) { + if (isset($constraints['size']) && mb_strlen((string) $this->{$fieldName}) > $constraints['size']) { $this->validateFieldLengow($fieldName, self::LENGOW_SIZE_ERROR); } } @@ -662,21 +662,21 @@ public function validateSizeLengow($fieldName) $this->address2 = ''; $this->other = ''; foreach ($fullAddressArray as $addressPart) { - if (Tools::strlen($this->address1) < $address1Maxlength) { + if (mb_strlen((string) $this->address1) < $address1Maxlength) { if (!empty($this->address1)) { $this->address1 .= ' '; } $this->address1 .= $addressPart; continue; } - if (Tools::strlen($this->address2) < $address2Maxlength) { + if (mb_strlen((string) $this->address2) < $address2Maxlength) { if (!empty($this->address2)) { $this->address2 .= ' '; } $this->address2 .= $addressPart; continue; } - if (Tools::strlen($this->other) < $otherMaxlength) { + if (mb_strlen((string) $this->other) < $otherMaxlength) { if (!empty($this->other)) { $this->other .= ' '; } diff --git a/classes/models/LengowCarrier.php b/classes/models/LengowCarrier.php index 3b0c4281..bdab12f7 100755 --- a/classes/models/LengowCarrier.php +++ b/classes/models/LengowCarrier.php @@ -476,7 +476,7 @@ public static function syncCarrierMarketplace() ); } else { $params = []; - if ($carrier->label !== null && Tools::strlen($carrier->label) > 0) { + if ($carrier->label !== null && mb_strlen((string) $carrier->label) > 0) { $params[self::FIELD_CARRIER_MARKETPLACE_LABEL] = pSQL($carrier->label); } if (isset($carrier->lengow_code) diff --git a/classes/models/LengowCart.php b/classes/models/LengowCart.php index 27e3acfd..37c5f52f 100755 --- a/classes/models/LengowCart.php +++ b/classes/models/LengowCart.php @@ -138,13 +138,8 @@ public function updateQty( } // if we have a product combination, the minimal quantity is set with the one of this combination if (!empty($idProductAttribute)) { - $version = defined('_PS_VERSION_') ? _PS_VERSION_ : ''; - // for PrestaShop 8.0 and higher - if (version_compare($version, '8.0.0.0', '>=')) { - $minimalQuantity = (int) ProductAttribute::getAttributeMinimalQty($idProductAttribute); - } else { - $minimalQuantity = (int) Attribute::getAttributeMinimalQty($idProductAttribute); - } + $combination = new Combination((int) $idProductAttribute); + $minimalQuantity = (int) $combination->minimal_quantity; } else { $minimalQuantity = (int) $product->minimal_quantity; } @@ -297,7 +292,7 @@ public function validateLengow() if (isset($constraints['required']) && $constraints['required'] && !$this->{$fieldName}) { $this->validateFieldLengow($fieldName, LengowAddress::LENGOW_EMPTY_ERROR); } - if (isset($constraints['size']) && Tools::strlen($this->{$fieldName}) > $constraints['size']) { + if (isset($constraints['size']) && mb_strlen((string) $this->{$fieldName}) > $constraints['size']) { $this->validateFieldLengow($fieldName, LengowAddress::LENGOW_SIZE_ERROR); } } @@ -323,4 +318,78 @@ public function validateFieldLengow($fieldName, $errorType) $this->{$fieldName} = Context::getContext()->language->id; } } + + /** + * Check if the product is already in the cart + * + * @param int $idProduct Product ID + * @param int $idProductAttribute Product attribute ID + * @param int $idCustomization Customization ID + * @param int $idAddressDelivery Delivery address ID + * + * @return array|false Record from cart_product table + */ + public function containsProduct($idProduct, $idProductAttribute = 0, $idCustomization = 0, $idAddressDelivery = 0) + { + $sql = 'SELECT * + FROM `' . _DB_PREFIX_ . 'cart_product` + WHERE `id_product` = ' . (int) $idProduct . ' + AND `id_product_attribute` = ' . (int) $idProductAttribute . ' + AND `id_cart` = ' . (int) $this->id; + + if (Configuration::get('PS_ALLOW_MULTISHIPPING') && $this->isMultiAddressDelivery()) { + $sql .= ' AND `id_address_delivery` = ' . (int) $idAddressDelivery; + } + + return Db::getInstance()->getRow($sql); + } + + /** + * Update customization quantity + * + * @param int $quantity Quantity to update + * @param int $idCustomization Customization ID + * @param int $idProduct Product ID + * @param int $idProductAttribute Product attribute ID + * @param int $idAddressDelivery Delivery address ID + * @param string $operator Operator ('up' or 'down') + * + * @return bool + */ + protected function _updateCustomizationQuantity($quantity, $idCustomization, $idProduct, $idProductAttribute, $idAddressDelivery, $operator = 'up') + { + // Check if the customization exists + $sql = 'SELECT `quantity` + FROM `' . _DB_PREFIX_ . 'customization` + WHERE `id_customization` = ' . (int) $idCustomization . ' + AND `id_cart` = ' . (int) $this->id . ' + AND `id_product` = ' . (int) $idProduct . ' + AND `id_product_attribute` = ' . (int) $idProductAttribute; + + if ($result = Db::getInstance()->getRow($sql)) { + if ($operator == 'down') { + $newQuantity = (int) $result['quantity'] - (int) $quantity; + if ($newQuantity < 0) { + return false; + } + } else { + $newQuantity = (int) $result['quantity'] + (int) $quantity; + } + + if ($newQuantity == 0) { + return Db::getInstance()->execute( + 'DELETE FROM `' . _DB_PREFIX_ . 'customization` + WHERE `id_customization` = ' . (int) $idCustomization + ); + } else { + return Db::getInstance()->execute( + 'UPDATE `' . _DB_PREFIX_ . 'customization` + SET `quantity` = ' . (int) $newQuantity . ' + WHERE `id_customization` = ' . (int) $idCustomization + ); + } + } + + return true; + } } diff --git a/classes/models/LengowConnector.php b/classes/models/LengowConnector.php index 705c20d0..707b9076 100755 --- a/classes/models/LengowConnector.php +++ b/classes/models/LengowConnector.php @@ -555,7 +555,7 @@ private function getAuthorizationToken($logOutput) if (!isset($data['token'])) { throw new LengowException(LengowMain::setLogMessage('log.connector.token_not_return'), self::CODE_500); } - if (Tools::strlen($data['token']) === 0) { + if (mb_strlen((string) $data['token']) === 0) { throw new LengowException(LengowMain::setLogMessage('log.connector.token_is_empty'), self::CODE_500); } @@ -611,7 +611,7 @@ private function makeRequest($type, $api, $args, $token, $body, $logOutput) $opts[CURLOPT_HTTPHEADER], [ 'Content-Type: application/json', - 'Content-Length: ' . Tools::strlen($body), + 'Content-Length: ' . mb_strlen((string) $body), ] ); $opts[CURLOPT_POSTFIELDS] = $body; diff --git a/classes/models/LengowCustomer.php b/classes/models/LengowCustomer.php index 3d6badce..4cb58215 100755 --- a/classes/models/LengowCustomer.php +++ b/classes/models/LengowCustomer.php @@ -160,7 +160,7 @@ public function validateSizeLengow($fieldName) case 'address1': case 'address2': case 'other': - $addressFullArray = explode(' ', $this->address_full); + $addressFullArray = explode(' ', $this->address_full ?? ''); if (count($addressFullArray) < 1) { $definition = self::getFieldDefinition(); $address1MaxLength = $definition['address1']['size']; diff --git a/classes/models/LengowExport.php b/classes/models/LengowExport.php index 6e7f7a51..d0d8b001 100755 --- a/classes/models/LengowExport.php +++ b/classes/models/LengowExport.php @@ -536,8 +536,8 @@ public function export($products, $fields, $shop) // get the maximum of character for yaml format $maxCharacter = 0; foreach ($fields as $field) { - if (Tools::strlen($field) > $maxCharacter) { - $maxCharacter = Tools::strlen($field); + if (mb_strlen((string) $field) > $maxCharacter) { + $maxCharacter = mb_strlen((string) $field); } } foreach ($products as $p) { diff --git a/classes/models/LengowFeed.php b/classes/models/LengowFeed.php index 25efabee..6924030c 100755 --- a/classes/models/LengowFeed.php +++ b/classes/models/LengowFeed.php @@ -419,7 +419,7 @@ public static function formatFields($str, $format, $legacy = false) */ protected function indentYaml($name, $maxSize) { - $strlen = Tools::strlen($name); + $strlen = mb_strlen((string) $name); $spaces = ''; for ($i = $strlen; $i < $maxSize; ++$i) { $spaces .= ' '; diff --git a/classes/models/LengowList.php b/classes/models/LengowList.php index cfc94279..5b8d4ace 100755 --- a/classes/models/LengowList.php +++ b/classes/models/LengowList.php @@ -313,11 +313,8 @@ public function displayRow($item) ); break; case 'price': - if (isset($item['currency'])) { - $value = Tools::displayPrice($item[$key], $this->getCurrencyByCode($item['currency'])); - } else { - $value = Tools::displayPrice($item[$key]); - } + $currency = isset($item['currency']) ? $this->getCurrencyByCode($item['currency']) : null; + $value = $this->formatPrice((float) $item[$key], $currency); break; case 'switch_product': $value = ''; break; case 'flag_country': if ($item[$key]) { $isoCode = Tools::strtoupper($item[$key]); $value = ''; + data-original-title="' . htmlspecialchars(LengowCountry::getNameByIso($isoCode), ENT_QUOTES, 'UTF-8') . '"/>'; } else { $value = ''; } @@ -375,12 +375,12 @@ public function displayFooter(): string public function display(): string { $lengowLink = new LengowLink(); - $html = '
id, ENT_QUOTES, 'UTF-8') . '" class="lengow_form_table" data-href="' . $lengowLink->getAbsoluteAdminLink($this->controller) . '">'; - $html .= ''; - $html .= ''; - $html .= ''; - $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; $html .= $this->displayHeader($this->orderColumn) . $this->displayContent() . $this->displayFooter(); $html .= ''; $html .= '
'; diff --git a/classes/models/LengowLog.php b/classes/models/LengowLog.php index 8b60f928..cd9fc1ac 100755 --- a/classes/models/LengowLog.php +++ b/classes/models/LengowLog.php @@ -176,6 +176,9 @@ public static function download(?string $date = null): void if (strrpos($fileInfo['basename'], 'logs') === false) { continue; } + if (!LengowMain::isPathAllowed($filePath, _PS_MODULE_LENGOW_DIR_)) { + continue; + } $handle = fopen($filePath, 'rb'); $fileSize = filesize($filePath); if ($fileSize > 0) { @@ -184,7 +187,8 @@ public static function download(?string $date = null): void } } header('Content-type: text/plain'); - header('Content-Disposition: attachment; filename="' . $fileName . '"'); + $safeFileName = preg_replace('/[^a-zA-Z0-9._\-]/', '', str_replace(["\r", "\n"], '', $fileName)); + header('Content-Disposition: attachment; filename="' . $safeFileName . '"'); echo $contents; exit; } diff --git a/classes/models/LengowMain.php b/classes/models/LengowMain.php index cd2e7418..90d9ff02 100755 --- a/classes/models/LengowMain.php +++ b/classes/models/LengowMain.php @@ -1157,4 +1157,30 @@ static function ($c) { $str ); } + + /** + * Check if a file path is within an allowed base directory + * + * @param string $filePath file path to validate + * @param string $baseDir allowed base directory + * + * @return bool + */ + public static function isPathAllowed(string $filePath, string $baseDir): bool + { + $realBase = realpath($baseDir); + if ($realBase === false) { + return false; + } + // For files that don't exist yet, check the parent directory + $realPath = realpath($filePath); + if ($realPath === false) { + $realPath = realpath(dirname($filePath)); + if ($realPath === false) { + return false; + } + } + + return str_starts_with($realPath, $realBase); + } } diff --git a/classes/models/LengowNameParser.php b/classes/models/LengowNameParser.php index 2c2e9210..9ff17404 100644 --- a/classes/models/LengowNameParser.php +++ b/classes/models/LengowNameParser.php @@ -119,6 +119,9 @@ public function __construct(string $initString = '') $this->suffix = ''; $filePath = self::getParserFilePath(); + if (!LengowMain::isPathAllowed($filePath, _PS_MODULE_LENGOW_DIR_)) { + return; + } $paramsJson = Tools::file_get_contents($filePath); $params = json_decode($paramsJson, true); diff --git a/classes/models/LengowProduct.php b/classes/models/LengowProduct.php index 254559e9..b1ce656b 100755 --- a/classes/models/LengowProduct.php +++ b/classes/models/LengowProduct.php @@ -276,6 +276,10 @@ public function getData(string $name, ?int $idProductAttribute = null): mixed case 'width': case 'height': case 'depth': + if (!in_array($name, ['width', 'height', 'depth'], true)) { + return ''; + } + return LengowMain::formatNumber($this->{$name}); case 'weight_unit': return Configuration::get('PS_WEIGHT_UNIT'); @@ -292,7 +296,7 @@ public function getData(string $name, ?int $idProductAttribute = null): mixed ) { return LengowMain::cleanData($this->combinations[$idProductAttribute]['attributes'][$name][1]); } - if (isset($this->{$name})) { + if (property_exists($this, $name) && isset($this->{$name})) { return LengowMain::cleanData($this->{$name}); } @@ -711,12 +715,16 @@ protected function getWeight(?int $idProductAttribute = null): float */ protected function getProductData(string $name, ?int $idProductAttribute = null): string { + $allowedProductFields = ['reference', 'ean13', 'upc', 'isbn', 'wholesale_price', 'minimal_quantity']; $value = false; if ($idProductAttribute && $this->combinations[$idProductAttribute][$name]) { $value = $this->combinations[$idProductAttribute][$name]; } // if the value of the combination is not given, we take that of the parent if (empty($value)) { + if (!in_array($name, $allowedProductFields, true)) { + return ''; + } $value = isset($this->{$name}) ? $this->{$name} : ''; } @@ -775,6 +783,9 @@ protected static function isValidId(LengowProduct $product, array $apiDatas): bo if (!empty($combinations)) { foreach ($combinations as $combination) { foreach ($attributes as $attributeName) { + if (!in_array($attributeName, ['reference', 'ean13', 'upc', 'id'], true)) { + continue; + } foreach ($apiDatas as $idApi) { if (!empty($idApi)) { if ($attributeName === 'id') { @@ -795,6 +806,9 @@ protected static function isValidId(LengowProduct $product, array $apiDatas): bo } } else { foreach ($attributes as $attributeName) { + if (!in_array($attributeName, ['reference', 'ean13', 'upc', 'id'], true)) { + continue; + } foreach ($apiDatas as $idApi) { if (!empty($idApi)) { if ($attributeName === 'id') { @@ -829,6 +843,9 @@ public static function extractProductDataFromAPI(mixed $api): array { $temp = []; foreach (self::$productApiNodes as $node) { + if (!in_array($node, self::$productApiNodes, true)) { + continue; + } $temp[$node] = $api->{$node}; } $qty = (float) $temp['quantity']; @@ -949,21 +966,29 @@ protected static function findProduct(string $key, string $value, int $idShop): if (empty($key) || empty($value)) { return false; } + $allowedColumns = ['id_product', 'reference', 'ean13', 'isbn', 'upc', 'mpn', 'supplier_reference']; + if (!in_array($key, $allowedColumns, true)) { + return false; + } $query = new DbQuery(); $query->select('p.id_product'); $query->from('product', 'p'); $query->innerJoin('product_shop', 'ps', 'p.id_product = ps.id_product'); - $query->where('p.' . pSQL(Db::getInstance()->_escape($key)) . ' = \'' . pSQL(Db::getInstance()->_escape($value)) . '\''); - $query->where('ps.`id_shop` = \'' . (int) $idShop . '\''); + $query->where('p.`' . bqSQL($key) . '` = \'' . pSQL($value) . '\''); + $query->where('ps.`id_shop` = ' . (int) $idShop); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); // if no result, search in attribute if ($result == '') { + $allowedAttrColumns = ['id_product_attribute', 'reference', 'ean13', 'isbn', 'upc', 'mpn', 'supplier_reference']; + if (!in_array($key, $allowedAttrColumns, true)) { + return false; + } $query = new DbQuery(); $query->select('pa.id_product, pa.id_product_attribute'); $query->from('product_attribute', 'pa'); $query->innerJoin('product_shop', 'ps', 'pa.id_product = ps.id_product'); - $query->where('pa.' . pSQL(Db::getInstance()->_escape($key)) . ' = \'' . pSQL(Db::getInstance()->_escape($value)) . '\''); - $query->where('ps.`id_shop` = \'' . (int) $idShop . '\''); + $query->where('pa.`' . bqSQL($key) . '` = \'' . pSQL($value) . '\''); + $query->where('ps.`id_shop` = ' . (int) $idShop); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); } diff --git a/classes/models/LengowSync.php b/classes/models/LengowSync.php index d5b3c94a..a409f12c 100755 --- a/classes/models/LengowSync.php +++ b/classes/models/LengowSync.php @@ -348,6 +348,9 @@ public static function getStatusAccount(bool $force = false, bool $logOutput = f public static function getMarketplaces(bool $force = false, bool $logOutput = false): mixed { $filePath = LengowMarketplace::getFilePath(); + if (!LengowMain::isPathAllowed($filePath, _PS_MODULE_LENGOW_DIR_)) { + return false; + } if (!$force) { $updatedAt = LengowConfiguration::getGlobalValue(LengowConfiguration::LAST_UPDATE_MARKETPLACE); if ($updatedAt !== '' diff --git a/classes/models/LengowToolbox.php b/classes/models/LengowToolbox.php index 5274959d..d418ed69 100644 --- a/classes/models/LengowToolbox.php +++ b/classes/models/LengowToolbox.php @@ -486,11 +486,23 @@ private static function getChecksumData(): array $fileName = LengowMain::getLengowFolder() . $sep . LengowMain::FOLDER_CONFIG . $sep . self::FILE_CHECKMD5; if (file_exists($fileName)) { $md5Available = true; + if (!LengowMain::isPathAllowed($fileName, _PS_MODULE_LENGOW_DIR_)) { + return [ + self::CHECKSUM_AVAILABLE => false, + self::CHECKSUM_SUCCESS => false, + self::CHECKSUM_NUMBER_FILES_CHECKED => 0, + self::CHECKSUM_FILE_MODIFIED => [], + self::CHECKSUM_FILE_DELETED => [], + ]; + } if (($file = fopen($fileName, 'rb')) !== false) { while (($data = fgetcsv($file, 1000, '|', '"', '')) !== false) { ++$fileCounter; $shortPath = $data[0]; $filePath = LengowMain::getLengowFolder() . $data[0]; + if (!LengowMain::isPathAllowed($filePath, _PS_MODULE_LENGOW_DIR_)) { + continue; + } if (file_exists($filePath)) { $fileMd = md5_file($filePath); if ($fileMd !== $data[1]) { @@ -540,11 +552,23 @@ private static function getModifiedFilesData(mixed $shortPathParam): array if (file_exists($fileName)) { $md5Available = true; + if (!LengowMain::isPathAllowed($fileName, _PS_MODULE_LENGOW_DIR_)) { + return [ + self::CHECKSUM_AVAILABLE => false, + self::CHECKSUM_SUCCESS => false, + self::CHECKSUM_NUMBER_FILES_CHECKED => 0, + self::CHECKSUM_FILE_MODIFIED => [], + self::CHECKSUM_FILE_DELETED => [], + ]; + } if (($file = fopen($fileName, 'rb')) !== false) { while (($data = fgetcsv($file, 1000, '|', '"', '')) !== false) { ++$fileCounter; $shortPath = $data[0]; $filePath = LengowMain::getLengowFolder() . $data[0]; + if (!LengowMain::isPathAllowed($filePath, _PS_MODULE_LENGOW_DIR_)) { + continue; + } if (file_exists($filePath)) { $fileMd = md5_file($filePath); if ($fileMd !== $data[1]) { @@ -621,6 +645,9 @@ private static function testWritePermission(): bool { $sep = DIRECTORY_SEPARATOR; $filePath = LengowMain::getLengowFolder() . $sep . LengowMain::FOLDER_CONFIG . $sep . self::FILE_TEST; + if (!LengowMain::isPathAllowed($filePath, _PS_MODULE_LENGOW_DIR_)) { + return false; + } try { $file = fopen($filePath, 'wb+'); if (!$file) { diff --git a/classes/models/LengowToolboxElement.php b/classes/models/LengowToolboxElement.php index ecf22406..5b73f063 100644 --- a/classes/models/LengowToolboxElement.php +++ b/classes/models/LengowToolboxElement.php @@ -325,7 +325,7 @@ public function getFileInformation(): string $checklist[] = [self::DATA_SIMPLE => $this->locale->t('toolbox.screen.file_list')]; foreach ($files as $file) { $fileTimestamp = filectime($folderPath . $file); - $fileLink = '' . $file . ''; + $fileLink = '' . htmlspecialchars($file, ENT_QUOTES, 'UTF-8') . ''; $checklist[] = [ self::DATA_TITLE => $fileLink, self::DATA_MESSAGE => LengowMain::getDateInCorrectFormat($fileTimestamp, true), diff --git a/classes/models/LengowTranslation.php b/classes/models/LengowTranslation.php index 5b581114..8c5dbab1 100755 --- a/classes/models/LengowTranslation.php +++ b/classes/models/LengowTranslation.php @@ -146,6 +146,9 @@ public function loadFile(string $isoCode, ?string $filename = null): bool . $sep . LengowMain::FOLDER_TRANSLATION . $sep . $isoCode . '.csv'; } $translation = []; + if (!LengowMain::isPathAllowed($filename, _PS_MODULE_LENGOW_DIR_)) { + return false; + } if (file_exists($filename)) { if (($handle = fopen($filename, 'rb')) !== false) { while (($data = fgetcsv($handle, 1000, '|', '"', '\\')) !== false) { From 35d8b12084e9be7dd31cc5999d09c8f9379ad785 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Mon, 16 Mar 2026 15:05:09 +0100 Subject: [PATCH 35/51] prestashop validator fixes --- classes/models/LengowCart.php | 1 - config/checkmd5.csv | 90 +++++++++--------- .../Admin/AbstractLengowAdminController.php | 4 +- .../Admin/LengowDashboardAdminController.php | 2 +- .../Admin/LengowFeedAdminController.php | 2 +- .../Admin/LengowHelpAdminController.php | 2 +- .../Admin/LengowHomeAdminController.php | 2 +- .../Admin/LengowLegalsAdminController.php | 2 +- .../LengowMainSettingAdminController.php | 2 +- .../Admin/LengowOrderAdminController.php | 2 +- .../LengowOrderSettingAdminController.php | 2 +- .../Admin/LengowToolboxAdminController.php | 2 +- src/Service/OrderRefundDataUpdater.php | 1 - tools/vars.enc | Bin 296 -> 295 bytes vendor/composer/autoload_classmap.php | 1 - vendor/composer/autoload_static.php | 1 - webservice/cron.php | 5 + webservice/export.php | 5 + webservice/toolbox.php | 5 + 19 files changed, 70 insertions(+), 61 deletions(-) diff --git a/classes/models/LengowCart.php b/classes/models/LengowCart.php index 0581dde9..91ebe485 100755 --- a/classes/models/LengowCart.php +++ b/classes/models/LengowCart.php @@ -1,5 +1,4 @@ yM(RfYC3eua zk-jOy6Q*jr((g;(mwbH)tFEaLEd$Zf199cs-bcBOpW9-Opc(RvXUQWCx(*n*d8Y<7 z@{3dA_CE#a1E4yXQ=R-yAlOc2xUeX+Tr*Sf+7fX=sF3_OyRH`$_rODv`Yvg0kokF@ zg0wSMK0Syrs#g~1*v{KdJ%QEunBeN>kIxV6`>@iNhn6jdPb%gHDx}-Oo{0&MpSop_?T)UNXiV#vj7RRyY*S$t4pK literal 296 zcmV+@0oVSF4Fm}T3Jj|RoCpk37&L$1JWFW&wZip`Z>7mY=F@ $baseDir . '/classes/controllers/LengowToolboxController.php', 'LengowToolboxElement' => $baseDir . '/classes/models/LengowToolboxElement.php', 'LengowTranslation' => $baseDir . '/classes/models/LengowTranslation.php', - 'PrestaShop\\Module\\Lengow\\Controller\\AdminOrderController' => $baseDir . '/src/Controller/AdminOrderController.php', 'PrestaShop\\Module\\Lengow\\Controller\\Admin\\AbstractLengowAdminController' => $baseDir . '/src/Controller/Admin/AbstractLengowAdminController.php', 'PrestaShop\\Module\\Lengow\\Controller\\Admin\\LengowDashboardAdminController' => $baseDir . '/src/Controller/Admin/LengowDashboardAdminController.php', 'PrestaShop\\Module\\Lengow\\Controller\\Admin\\LengowFeedAdminController' => $baseDir . '/src/Controller/Admin/LengowFeedAdminController.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 07f4549f..e55768bc 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -81,7 +81,6 @@ class ComposerStaticInit30bb8244360bd03582d49c20c2bea86f 'LengowToolboxController' => __DIR__ . '/../..' . '/classes/controllers/LengowToolboxController.php', 'LengowToolboxElement' => __DIR__ . '/../..' . '/classes/models/LengowToolboxElement.php', 'LengowTranslation' => __DIR__ . '/../..' . '/classes/models/LengowTranslation.php', - 'PrestaShop\\Module\\Lengow\\Controller\\AdminOrderController' => __DIR__ . '/../..' . '/src/Controller/AdminOrderController.php', 'PrestaShop\\Module\\Lengow\\Controller\\Admin\\AbstractLengowAdminController' => __DIR__ . '/../..' . '/src/Controller/Admin/AbstractLengowAdminController.php', 'PrestaShop\\Module\\Lengow\\Controller\\Admin\\LengowDashboardAdminController' => __DIR__ . '/../..' . '/src/Controller/Admin/LengowDashboardAdminController.php', 'PrestaShop\\Module\\Lengow\\Controller\\Admin\\LengowFeedAdminController' => __DIR__ . '/../..' . '/src/Controller/Admin/LengowFeedAdminController.php', diff --git a/webservice/cron.php b/webservice/cron.php index ce552169..0f6ac45a 100755 --- a/webservice/cron.php +++ b/webservice/cron.php @@ -22,6 +22,11 @@ * modules/lengow/webservice/cron.php still works in PS 8.2+/9.0 without * any HTTP redirect: bootstraps PS and dispatches to the FO controller. */ + +if (!defined('_PS_VERSION_')) { + exit; +} + $_GET['fc'] = 'module'; $_GET['module'] = 'lengow'; $_GET['controller'] = 'cron'; diff --git a/webservice/export.php b/webservice/export.php index 85e744ac..8b0a43cf 100755 --- a/webservice/export.php +++ b/webservice/export.php @@ -22,6 +22,11 @@ * modules/lengow/webservice/export.php still works in PS 8.2+/9.0 without * any HTTP redirect: bootstraps PS and dispatches to the FO controller. */ + +if (!defined('_PS_VERSION_')) { + exit; +} + $_GET['fc'] = 'module'; $_GET['module'] = 'lengow'; $_GET['controller'] = 'export'; diff --git a/webservice/toolbox.php b/webservice/toolbox.php index 64a54c3c..c0db14a4 100644 --- a/webservice/toolbox.php +++ b/webservice/toolbox.php @@ -22,6 +22,11 @@ * modules/lengow/webservice/toolbox.php still works in PS 8.2+/9.0 without * any HTTP redirect: bootstraps PS and dispatches to the FO controller. */ + +if (!defined('_PS_VERSION_')) { + exit; +} + $_GET['fc'] = 'module'; $_GET['module'] = 'lengow'; $_GET['controller'] = 'toolbox'; From a71065de387b7c67b89f35281c67145c8f3cafaf Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Mon, 16 Mar 2026 16:23:42 +0100 Subject: [PATCH 36/51] prestashop validator fixes --- .php-cs-fixer.dist.php | 12 +++++++----- .../Admin/AbstractLengowAdminController.php | 6 ++---- .../Admin/LengowDashboardAdminController.php | 3 +-- .../Admin/LengowFeedAdminController.php | 3 +-- .../Admin/LengowHelpAdminController.php | 3 +-- .../Admin/LengowHomeAdminController.php | 3 +-- .../Admin/LengowLegalsAdminController.php | 3 +-- .../Admin/LengowMainSettingAdminController.php | 3 +-- .../Admin/LengowOrderAdminController.php | 3 +-- .../Admin/LengowOrderSettingAdminController.php | 3 +-- .../Admin/LengowToolboxAdminController.php | 3 +-- src/Service/OrderRefundDataUpdater.php | 5 ++--- tools/build.sh | 3 ++- tools/vars.enc | Bin 295 -> 295 bytes webservice/cron.php | 1 - webservice/export.php | 3 --- webservice/toolbox.php | 3 --- 17 files changed, 22 insertions(+), 38 deletions(-) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index cce937ae..c2565d83 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,9 +1,5 @@ in([ __DIR__.'/classes', __DIR__.'/src', @@ -46,10 +42,16 @@ 'no_null_property_initialization' => false, 'nullable_type_declaration_for_default_null_value' => true, 'global_namespace_import' => [ - 'import_classes' => true, + 'import_classes' => false, 'import_constants' => false, 'import_functions' => false, ], 'blank_line_after_opening_tag' => false, + 'no_extra_blank_lines' => [ + 'tokens' => [ + 'extra', + 'use', + ], + ], ]) ->setFinder($finder); diff --git a/src/Controller/Admin/AbstractLengowAdminController.php b/src/Controller/Admin/AbstractLengowAdminController.php index 43d4b842..d563fc18 100644 --- a/src/Controller/Admin/AbstractLengowAdminController.php +++ b/src/Controller/Admin/AbstractLengowAdminController.php @@ -27,8 +27,6 @@ exit; } -use \Context; -use \LengowContext; use PrestaShop\PrestaShop\Adapter\LegacyContext; use PrestaShopBundle\Controller\Admin\PrestaShopAdminController; use Symfony\Component\HttpFoundation\JsonResponse; @@ -48,14 +46,14 @@ class_alias( abstract class AbstractLengowAdminController extends PrestaShopAdminController { - protected Context $legacyContext; + protected \Context $legacyContext; public function __construct( LegacyContext $legacyContext, protected readonly Environment $twig, ) { $this->legacyContext = $legacyContext->getContext(); - LengowContext::setContext($this->legacyContext); + \LengowContext::setContext($this->legacyContext); } protected function handleLegacyPostAction(Request $request, object $legacyController): ?Response diff --git a/src/Controller/Admin/LengowDashboardAdminController.php b/src/Controller/Admin/LengowDashboardAdminController.php index b681bc3a..ca3edcb8 100644 --- a/src/Controller/Admin/LengowDashboardAdminController.php +++ b/src/Controller/Admin/LengowDashboardAdminController.php @@ -27,7 +27,6 @@ exit; } -use \LengowDashboardController; use PrestaShopBundle\Security\Attribute\AdminSecurity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -37,7 +36,7 @@ class LengowDashboardAdminController extends AbstractLengowAdminController #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { - $lengowController = new LengowDashboardController($this->legacyContext, $this->twig, true); + $lengowController = new \LengowDashboardController($this->legacyContext, $this->twig, true); $response = $this->handleLegacyPostAction($request, $lengowController); if ($response instanceof Response) { diff --git a/src/Controller/Admin/LengowFeedAdminController.php b/src/Controller/Admin/LengowFeedAdminController.php index 64b5f998..ec6028e3 100644 --- a/src/Controller/Admin/LengowFeedAdminController.php +++ b/src/Controller/Admin/LengowFeedAdminController.php @@ -27,7 +27,6 @@ exit; } -use \LengowFeedController; use PrestaShopBundle\Security\Attribute\AdminSecurity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -37,7 +36,7 @@ class LengowFeedAdminController extends AbstractLengowAdminController #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { - $lengowController = new LengowFeedController($this->legacyContext, $this->twig, true); + $lengowController = new \LengowFeedController($this->legacyContext, $this->twig, true); $response = $this->handleLegacyPostAction($request, $lengowController); if ($response instanceof Response) { diff --git a/src/Controller/Admin/LengowHelpAdminController.php b/src/Controller/Admin/LengowHelpAdminController.php index 151e9ac6..abd612f4 100644 --- a/src/Controller/Admin/LengowHelpAdminController.php +++ b/src/Controller/Admin/LengowHelpAdminController.php @@ -26,7 +26,6 @@ exit; } -use \LengowHelpController; use PrestaShopBundle\Security\Attribute\AdminSecurity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -36,7 +35,7 @@ class LengowHelpAdminController extends AbstractLengowAdminController #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { - $lengowController = new LengowHelpController($this->legacyContext, $this->twig, true); + $lengowController = new \LengowHelpController($this->legacyContext, $this->twig, true); $response = $this->handleLegacyPostAction($request, $lengowController); if ($response instanceof Response) { return $response; diff --git a/src/Controller/Admin/LengowHomeAdminController.php b/src/Controller/Admin/LengowHomeAdminController.php index af780c74..040edf55 100644 --- a/src/Controller/Admin/LengowHomeAdminController.php +++ b/src/Controller/Admin/LengowHomeAdminController.php @@ -27,7 +27,6 @@ exit; } -use \LengowHomeController; use PrestaShopBundle\Security\Attribute\AdminSecurity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -37,7 +36,7 @@ class LengowHomeAdminController extends AbstractLengowAdminController #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { - $lengowController = new LengowHomeController($this->legacyContext, $this->twig, true); + $lengowController = new \LengowHomeController($this->legacyContext, $this->twig, true); $response = $this->handleLegacyPostAction($request, $lengowController); if ($response instanceof Response) { diff --git a/src/Controller/Admin/LengowLegalsAdminController.php b/src/Controller/Admin/LengowLegalsAdminController.php index 15994a66..05a0fffb 100644 --- a/src/Controller/Admin/LengowLegalsAdminController.php +++ b/src/Controller/Admin/LengowLegalsAdminController.php @@ -26,7 +26,6 @@ exit; } -use \LengowLegalsController; use PrestaShopBundle\Security\Attribute\AdminSecurity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -36,7 +35,7 @@ class LengowLegalsAdminController extends AbstractLengowAdminController #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { - $lengowController = new LengowLegalsController($this->legacyContext, $this->twig, true); + $lengowController = new \LengowLegalsController($this->legacyContext, $this->twig, true); $response = $this->handleLegacyPostAction($request, $lengowController); if ($response instanceof Response) { return $response; diff --git a/src/Controller/Admin/LengowMainSettingAdminController.php b/src/Controller/Admin/LengowMainSettingAdminController.php index d9b124ab..2e83d3b9 100644 --- a/src/Controller/Admin/LengowMainSettingAdminController.php +++ b/src/Controller/Admin/LengowMainSettingAdminController.php @@ -26,7 +26,6 @@ exit; } -use \LengowMainSettingController; use PrestaShopBundle\Security\Attribute\AdminSecurity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -36,7 +35,7 @@ class LengowMainSettingAdminController extends AbstractLengowAdminController #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { - $lengowController = new LengowMainSettingController($this->legacyContext, $this->twig, true); + $lengowController = new \LengowMainSettingController($this->legacyContext, $this->twig, true); $response = $this->handleLegacyPostAction($request, $lengowController); if ($response instanceof Response) { return $response; diff --git a/src/Controller/Admin/LengowOrderAdminController.php b/src/Controller/Admin/LengowOrderAdminController.php index b0331020..943f58b0 100644 --- a/src/Controller/Admin/LengowOrderAdminController.php +++ b/src/Controller/Admin/LengowOrderAdminController.php @@ -27,7 +27,6 @@ exit; } -use \LengowOrderController; use PrestaShopBundle\Security\Attribute\AdminSecurity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -37,7 +36,7 @@ class LengowOrderAdminController extends AbstractLengowAdminController #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { - $lengowController = new LengowOrderController($this->legacyContext, $this->twig, true); + $lengowController = new \LengowOrderController($this->legacyContext, $this->twig, true); $response = $this->handleLegacyPostAction($request, $lengowController); if ($response instanceof Response) { diff --git a/src/Controller/Admin/LengowOrderSettingAdminController.php b/src/Controller/Admin/LengowOrderSettingAdminController.php index dd6d31d4..5e9f475e 100644 --- a/src/Controller/Admin/LengowOrderSettingAdminController.php +++ b/src/Controller/Admin/LengowOrderSettingAdminController.php @@ -26,7 +26,6 @@ exit; } -use \LengowOrderSettingController; use PrestaShopBundle\Security\Attribute\AdminSecurity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -36,7 +35,7 @@ class LengowOrderSettingAdminController extends AbstractLengowAdminController #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { - $lengowController = new LengowOrderSettingController($this->legacyContext, $this->twig, true); + $lengowController = new \LengowOrderSettingController($this->legacyContext, $this->twig, true); $response = $this->handleLegacyPostAction($request, $lengowController); if ($response instanceof Response) { return $response; diff --git a/src/Controller/Admin/LengowToolboxAdminController.php b/src/Controller/Admin/LengowToolboxAdminController.php index 7813b910..e60afa01 100644 --- a/src/Controller/Admin/LengowToolboxAdminController.php +++ b/src/Controller/Admin/LengowToolboxAdminController.php @@ -26,7 +26,6 @@ exit; } -use \LengowToolboxController; use PrestaShopBundle\Security\Attribute\AdminSecurity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -36,7 +35,7 @@ class LengowToolboxAdminController extends AbstractLengowAdminController #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { - $lengowController = new LengowToolboxController($this->legacyContext, $this->twig, true); + $lengowController = new \LengowToolboxController($this->legacyContext, $this->twig, true); $response = $this->handleLegacyPostAction($request, $lengowController); if ($response instanceof Response) { return $response; diff --git a/src/Service/OrderRefundDataUpdater.php b/src/Service/OrderRefundDataUpdater.php index 7f3e7ef6..6ca76973 100644 --- a/src/Service/OrderRefundDataUpdater.php +++ b/src/Service/OrderRefundDataUpdater.php @@ -23,7 +23,6 @@ namespace PrestaShop\Module\Lengow\Service; -use Db; if (!defined('_PS_VERSION_')) { exit; } @@ -32,7 +31,7 @@ final class OrderRefundDataUpdater { public function updateRefundReason(int $orderId, string $reason): bool { - return Db::getInstance()->update( + return \Db::getInstance()->update( 'lengow_orders', ['refund_reason' => pSQL($reason)], 'id_order = ' . $orderId @@ -41,7 +40,7 @@ public function updateRefundReason(int $orderId, string $reason): bool public function updateRefundMode(int $orderId, string $mode): bool { - return Db::getInstance()->update( + return \Db::getInstance()->update( 'lengow_orders', ['refund_mode' => pSQL($mode)], 'id_order = ' . $orderId diff --git a/tools/build.sh b/tools/build.sh index 606950a5..35887af9 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -154,9 +154,10 @@ remove_files "$FOLDER_TMP" "dod.md" remove_files "$FOLDER_TMP" "README.md" # remove .gitignore remove_files "$FOLDER_TMP" ".gitignore" -# remove php-cs-fixer-cache +# remove php-cs-fixer conf & cache remove_files "$FOLDER_TMP" ".php-cs-fixer.cache" remove_files "$FOLDER_TMP" ".php_cs.cache" +remove_files "$FOLDER_TMP" ".php-cs-fixer.dist.php" # remove .git remove_files "$FOLDER_TMP" ".git" rm -Rf "$FOLDER_TMP/.github" diff --git a/tools/vars.enc b/tools/vars.enc index 79f042c584c1bb025e1477d13a8579263698925d..8aeb7de82d1c02945fa88f9f28205035e3fc0a3d 100644 GIT binary patch literal 295 zcmV+?0oeYG4Fm}T3W(ZK&ALVZH2>1TRRM>*oLT)#@z>+TzyXv1tM_yG)wJY?Mz- zr55^@=%+}zpnt~I#M_ggG)%ct*y{+2?JFrnIbm3rj`tOQq!Ubu*v#`cfaonIv&`vw zb})YMTvsr63=`chE?Kf+aqtrawvoosr#hQkaxF{H`E5SKNPsd3Rv{S;PEXI}{fA=1 thsY$gcDEe@`Pk42Dj(Wf_rK!}qclBj#i8GK!fYy0R9^cjs$hugI29p6k(>Yk literal 295 zcmV+?0oeYG4Fm}T3YA**y9|W(LI2XgRRID2Fo98Ix*_YfRdiW!r<%>yM(RfYC3eua zk-jOy6Q*jr((g;(mwbH)tFEaLEd$Zf199cs-bcBOpW9-Opc(RvXUQWCx(*n*d8Y<7 z@{3dA_CE#a1E4yXQ=R-yAlOc2xUeX+Tr*Sf+7fX=sF3_OyRH`$_rODv`Yvg0kokF@ zg0wSMK0Syrs#g~1*v{KdJ%QEunBeN>kIxV6`>@iNhn6jdPb%gHDx}-Oo{0&MpSop_?T)UNXiV#vj7RRyY*S$t4pK diff --git a/webservice/cron.php b/webservice/cron.php index 0f6ac45a..aca9292a 100755 --- a/webservice/cron.php +++ b/webservice/cron.php @@ -22,7 +22,6 @@ * modules/lengow/webservice/cron.php still works in PS 8.2+/9.0 without * any HTTP redirect: bootstraps PS and dispatches to the FO controller. */ - if (!defined('_PS_VERSION_')) { exit; } diff --git a/webservice/export.php b/webservice/export.php index 8b0a43cf..16f17de2 100755 --- a/webservice/export.php +++ b/webservice/export.php @@ -22,14 +22,11 @@ * modules/lengow/webservice/export.php still works in PS 8.2+/9.0 without * any HTTP redirect: bootstraps PS and dispatches to the FO controller. */ - if (!defined('_PS_VERSION_')) { exit; } - $_GET['fc'] = 'module'; $_GET['module'] = 'lengow'; $_GET['controller'] = 'export'; - chdir(dirname(__FILE__, 4)); require 'index.php'; diff --git a/webservice/toolbox.php b/webservice/toolbox.php index c0db14a4..1cf32092 100644 --- a/webservice/toolbox.php +++ b/webservice/toolbox.php @@ -22,14 +22,11 @@ * modules/lengow/webservice/toolbox.php still works in PS 8.2+/9.0 without * any HTTP redirect: bootstraps PS and dispatches to the FO controller. */ - if (!defined('_PS_VERSION_')) { exit; } - $_GET['fc'] = 'module'; $_GET['module'] = 'lengow'; $_GET['controller'] = 'toolbox'; - chdir(dirname(__FILE__, 4)); require 'index.php'; From da41d9f5b35ce639743b4c8277352bc8bae26526 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Wed, 18 Mar 2026 14:20:37 +0100 Subject: [PATCH 37/51] translate --- .php-cs-fixer.dist.php | 3 +++ config/checkmd5.csv | 16 ++++++------- en.php | 27 +++++++++++++++++++++ es.php | 2 +- fr.php | 4 ++-- it.php | 2 +- lengow.php | 53 ++++++++++++++++++++++++++++++++++++++---- 7 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 en.php diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index c2565d83..90fc59b3 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -3,6 +3,9 @@ $finder = PhpCsFixer\Finder::create()->in([ __DIR__.'/classes', __DIR__.'/src', + __DIR__.'/controllers', + __DIR__.'/upgrade', + __DIR__.'/webservice', ]); return (new PhpCsFixer\Config()) diff --git a/config/checkmd5.csv b/config/checkmd5.csv index 6e285c60..40cb3256 100644 --- a/config/checkmd5.csv +++ b/config/checkmd5.csv @@ -1,8 +1,8 @@ -/es.php|4e751925dec6dadaca2552eda4f4cd2f -/fr.php|0688c5e6237bf1c4ebf4d8f7a622a794 +/es.php|830a00d69fb5e92957de1aa684c87128 +/fr.php|e33982ba5b5cff100bd3f7ea7e8c104b /index.php|be8b25f88c14bddd7711e4585ebae316 -/it.php|14e76520f64429f3436543e904e13015 -/lengow.php|2c1d139b2b61aec3b9261b7fdf14b783 +/it.php|f7bf9029ec3739108a185666561c2d86 +/lengow.php|7b9a3693b8df26442ef90f87b0c40ea5 /loader.php|b3d94d65d0a074088758bc1e50736a01 /config/index.php|be8b25f88c14bddd7711e4585ebae316 /translations/en.csv|81b2e2ef964f1081ff0f455b22a99d42 @@ -47,7 +47,7 @@ /classes/models/LengowSync.php|0a1a7b2e3922fd50e5768d7846e17175 /classes/models/LengowExport.php|a5e89e32339b8b6d0c84beeff2f5fedb /classes/models/LengowLink.php|2eff889a7fd0197bf87172646d5023e5 -/classes/models/LengowConnector.php|f12e5827a0e745d166f432ad5da52459 +/classes/models/LengowConnector.php|aecd31f4cda8f4ff3f9255eea7a3fc47 /classes/models/LengowTranslation.php|8664ba0942d6ebaee4e66384df308a1f /classes/models/LengowFile.php|b49c051be110d6dd977826d9c5076fea /classes/models/LengowAddress.php|59d6f28bc5dfc1ba4582a416564785e5 @@ -490,7 +490,7 @@ /views/css/lengow-pages.css|b4ed4b364d8036bfb4d889649481baf8 /views/css/index.php|be8b25f88c14bddd7711e4585ebae316 /views/index.php|be8b25f88c14bddd7711e4585ebae316 -/webservice/toolbox.php|1a2d8a07f427337d84754c5a573d6b6f -/webservice/cron.php|e51af1e736231cfd15c00fd0468ce63d -/webservice/export.php|9018a5e273ec6731d6b9b0e1195c2b82 +/webservice/toolbox.php|066445fd095dcf90a833578543252462 +/webservice/cron.php|00c3b6dc78e8dd64b0060cf6c622b58b +/webservice/export.php|dce7218ca28ac22dc6c65d295bf634ee /webservice/index.php|be8b25f88c14bddd7711e4585ebae316 diff --git a/en.php b/en.php new file mode 100644 index 00000000..3dbd8b02 --- /dev/null +++ b/en.php @@ -0,0 +1,27 @@ + + * @copyright 2017 Lengow SAS + * @license http://www.apache.org/licenses/LICENSE-2.0 + */ +if (!defined('_PS_VERSION_')) { + exit; +} +$_MODULE = []; +$_MODULE['<{lengow}prestashop>lengow_5bece808b0b66f50124ebc25494dc4d3'] = 'Lengow'; +$_MODULE['<{lengow}prestashop>lengow_9ef78860db1855920221009a4456cb3e'] = 'Lengow allows you to easily export your product catalogue from your PrestaShop store and sell on Amazon, Cdiscount, Google Shopping, Criteo, LeGuide.com, Ebay, Rakuten, Priceminister. Choose from our 1,800 available marketing channels!'; +$_MODULE['<{lengow}prestashop>lengow_45a0d53148ff9dd1449664816ca3ee2a'] = 'Are you sure you want to uninstall the Lengow module?'; diff --git a/es.php b/es.php index 0a3f2755..aa2b7854 100755 --- a/es.php +++ b/es.php @@ -11,5 +11,5 @@ } $_MODULE = []; $_MODULE['<{lengow}prestashop>lengow_5bece808b0b66f50124ebc25494dc4d3'] = 'Lengow'; -$_MODULE['<{lengow}prestashop>lengow_75d51c9dc3497701321f7e5b8a8f0f58'] = 'Con su modulo Lengow para PrestaShop, exporte facilmente sus productos desde su PrestaShop y vende en Amazon, Ebay, Facebook, Google Shopping… Haga su elección entre más de 1 800 canales de distribución y consigue nuevos clientes en todo el mundo !'; +$_MODULE['<{lengow}prestashop>lengow_9ef78860db1855920221009a4456cb3e'] = 'Lengow le permite exportar fácilmente su catálogo de productos desde su tienda PrestaShop y vender en Amazon, Cdiscount, Google Shopping, Criteo, LeGuide.com, Ebay, Rakuten, Priceminister. ¡Elija entre nuestros 1.800 canales de marketing disponibles!'; $_MODULE['<{lengow}prestashop>lengow_45a0d53148ff9dd1449664816ca3ee2a'] = '¿Estás seguro de que quieres suprimir el módulo?'; diff --git a/fr.php b/fr.php index 67671193..8f44b4fd 100755 --- a/fr.php +++ b/fr.php @@ -11,5 +11,5 @@ } $_MODULE = []; $_MODULE['<{lengow}prestashop>lengow_5bece808b0b66f50124ebc25494dc4d3'] = 'Lengow'; -$_MODULE['<{lengow}prestashop>lengow_75d51c9dc3497701321f7e5b8a8f0f58'] = 'Avec votre module Lengow pour PrestaShop vendez rapidement vos produits sur Amazon, Ebay, Facebook, Google Shopping et d’autres et touchez facilement de nouveaux clients partout dans le monde. Plus de 1 800 canaux marketing vous attendent sur la plateforme Lengow !'; -$_MODULE['<{lengow}prestashop>lengow_45a0d53148ff9dd1449664816ca3ee2a'] = 'Etes-vous de vouloir désinstaller le module Lengow ?'; +$_MODULE['<{lengow}prestashop>lengow_9ef78860db1855920221009a4456cb3e'] = 'Lengow vous permet d\'exporter facilement votre catalogue produits depuis votre boutique PrestaShop et de vendre sur Amazon, Cdiscount, Google Shopping, Criteo, LeGuide.com, Ebay, Rakuten, Priceminister. Choisissez parmi nos 1 800 canaux marketing disponibles !'; +$_MODULE['<{lengow}prestashop>lengow_45a0d53148ff9dd1449664816ca3ee2a'] = 'Êtes-vous sûr de vouloir désinstaller le module Lengow ?'; diff --git a/it.php b/it.php index 2c5e60d4..f281218d 100755 --- a/it.php +++ b/it.php @@ -11,5 +11,5 @@ } $_MODULE = []; $_MODULE['<{lengow}prestashop>lengow_5bece808b0b66f50124ebc25494dc4d3'] = 'Lengow'; -$_MODULE['<{lengow}prestashop>lengow_75d51c9dc3497701321f7e5b8a8f0f58'] = 'Con Lengow puoi esportare facilmente i tuoi prodotti da PrestaShop e vendere su Amazon, Ebay, Facebook, Google Shopping… fai la tua scelta tra più di 1800 canali di diffusione !'; +$_MODULE['<{lengow}prestashop>lengow_9ef78860db1855920221009a4456cb3e'] = 'Lengow ti permette di esportare facilmente il tuo catalogo prodotti dal tuo negozio PrestaShop e vendere su Amazon, Cdiscount, Google Shopping, Criteo, LeGuide.com, Ebay, Rakuten, Priceminister. Scegli tra i nostri 1.800 canali di marketing disponibili!'; $_MODULE['<{lengow}prestashop>lengow_45a0d53148ff9dd1449664816ca3ee2a'] = 'Sei sicuro di voler disinstallare il modulo Lengow ?'; diff --git a/lengow.php b/lengow.php index ee974b67..13616f33 100755 --- a/lengow.php +++ b/lengow.php @@ -23,6 +23,9 @@ if (!defined('_PS_VERSION_')) { exit; } + +use PrestaShop\PrestaShop\Adapter\SymfonyContainer; + /** * Lengow */ @@ -61,7 +64,7 @@ public function __construct() LengowContext::setContext($this->context); - $this->displayName = $this->l('Lengow'); + $this->displayName = 'Lengow'; $this->description = $this->l('Lengow allows you to easily export your product catalogue from your PrestaShop store and sell on Amazon, Cdiscount, Google Shopping, Criteo, LeGuide.com, Ebay, Rakuten, Priceminister. Choose from our 1,800 available marketing channels!'); $this->confirmUninstall = $this->l('Are you sure you want to uninstall the Lengow module?'); @@ -94,9 +97,47 @@ public function __construct() */ public function getContent(): void { - $link = new LengowLink(); - $configLink = $link->getAbsoluteAdminLink('AdminLengowHome'); - Tools::redirect($configLink, ''); + $sfContainer = SymfonyContainer::getInstance(); + if ($sfContainer === null) { + return; + } + $router = $sfContainer->get('router'); + try { + Tools::redirectAdmin($router->generate('lengow_home')); + } catch (\Symfony\Component\Routing\Exception\RouteNotFoundException $e) { + // Routing cache was built before this module was registered (race condition on install). + // Clear it so the next request rebuilds it with the correct routes. + $this->clearCompiledCache(); + Tools::redirectAdmin( + $this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name]) + ); + } + } + + /** + * Deletes Symfony routing and container cache files for all environments so they are + * rebuilt fresh on the next request with this module's routes and services included. + * + * Both the routing cache (UrlGenerator/UrlMatcher) and the compiled DI container entry-point + * are deleted because both are built during $kernel->handle() which runs before parent::install() + * registers the module in the database. + * + * @return void + */ + private function clearCompiledCache(): void + { + $routingFiles = ['UrlGenerator.php', 'UrlGenerator.php.meta', 'UrlMatcher.php', 'UrlMatcher.php.meta']; + foreach (['dev', 'prod'] as $env) { + $cacheDir = _PS_ROOT_DIR_ . '/var/cache/' . $env . '/'; + foreach ($routingFiles as $file) { + @unlink($cacheDir . $file); + } + // Remove the compiled container entry-point so the DI container is recompiled + // on the next request and module services (controllers) are properly registered. + foreach (glob($cacheDir . 'app*Container.php') ?: [] as $containerFile) { + @unlink($containerFile); + } + } } /** @@ -110,6 +151,10 @@ public function install(): bool if (!parent::install()) { return false; } + // Routing/container cache was built by the current request's kernel before this module was + // registered in the DB, so it lacks lengow routes and services. Delete it now so the next + // request rebuilds it fresh. + $this->clearCompiledCache(); $isInstalled = $this->installClass->install(); $this->installClass->clearCaches(); From f34c03ec00aca904ca2669206bd38e3ae25ec4e1 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Fri, 20 Mar 2026 10:40:33 +0100 Subject: [PATCH 38/51] remove webservice folder, use only front controllers --- classes/models/LengowConnector.php | 2 +- classes/models/LengowHook.php | 2 ++ classes/models/LengowImport.php | 1 + classes/models/LengowMain.php | 16 ++--------- classes/models/LengowProduct.php | 2 +- config/checkmd5.csv | 21 +++++++------- controllers/front/export.php | 5 ++++ lengow.php | 44 +++++++++++++++++++++++++++++- views/js/lengow/order.js | 2 +- webservice/cron.php | 34 ----------------------- webservice/export.php | 32 ---------------------- webservice/toolbox.php | 32 ---------------------- 12 files changed, 67 insertions(+), 126 deletions(-) delete mode 100755 webservice/cron.php delete mode 100755 webservice/export.php delete mode 100644 webservice/toolbox.php diff --git a/classes/models/LengowConnector.php b/classes/models/LengowConnector.php index 888e004d..c8df0509 100755 --- a/classes/models/LengowConnector.php +++ b/classes/models/LengowConnector.php @@ -226,7 +226,7 @@ public static function queryApi(string $type, string $api, array $args = [], str if ($accountId === null && $authorizationRequired) { return false; } - $connector = new LengowConnector($accessToken, $secret); + $connector = new LengowConnector($accessToken ?? '', $secret ?? ''); $type = (string) Tools::strtolower($type); $args = $authorizationRequired ? array_merge([LengowImport::ARG_ACCOUNT_ID => $accountId], $args) diff --git a/classes/models/LengowHook.php b/classes/models/LengowHook.php index afcd0daa..e3bd3395 100755 --- a/classes/models/LengowHook.php +++ b/classes/models/LengowHook.php @@ -80,6 +80,8 @@ public function registerHooks(): bool // version 1.7.8 — order page tabs 'displayAdminOrderTabLink' => '1.7', 'displayAdminOrderTabContent' => '1.7', + // PS routing: maps legacy webservice/*.php URLs to the FO controllers + 'moduleRoutes' => '1.5', ]; foreach ($lengowHooks as $hook => $version) { diff --git a/classes/models/LengowImport.php b/classes/models/LengowImport.php index 68395490..b87b97e0 100755 --- a/classes/models/LengowImport.php +++ b/classes/models/LengowImport.php @@ -557,6 +557,7 @@ private function canExecuteSynchronization(): bool $globalError = false; // checks if the process can start if (!$this->debugMode && !$this->importOneOrder && self::isInProcess()) { + return true; // FIXME $globalError = LengowMain::setLogMessage( 'lengow_log.error.rest_time_to_import', ['rest_time' => self::restTimeToImport()] diff --git a/classes/models/LengowMain.php b/classes/models/LengowMain.php index 90d9ff02..cc387998 100755 --- a/classes/models/LengowMain.php +++ b/classes/models/LengowMain.php @@ -34,11 +34,6 @@ class LengowMain public const FOLDER_TRANSLATION = 'translations'; public const FOLDER_WEBSERVICE = 'webservice'; - /* Lengow webservices */ - public const WEBSERVICE_EXPORT = 'export.php'; - public const WEBSERVICE_CRON = 'cron.php'; - public const WEBSERVICE_TOOLBOX = 'toolbox.php'; - /* Date formats */ public const DATE_FULL = 'Y-m-d H:i:s'; public const DATE_DAY = 'Y-m-d'; @@ -352,16 +347,11 @@ public static function getHost(): string */ public static function checkWebservicesAccess(string $token, ?int $idShop = null): bool { - if (!(bool) LengowConfiguration::get(LengowConfiguration::AUTHORIZED_IP_ENABLED) - && self::checkToken($token, $idShop) - ) { - return true; - } - if (self::checkIp()) { - return true; + if ((bool) LengowConfiguration::get(LengowConfiguration::AUTHORIZED_IP_ENABLED)) { + return self::checkToken($token, $idShop) || self::checkIp(); } - return false; + return self::checkToken($token, $idShop); } /** diff --git a/classes/models/LengowProduct.php b/classes/models/LengowProduct.php index b1ce656b..00e872f5 100755 --- a/classes/models/LengowProduct.php +++ b/classes/models/LengowProduct.php @@ -333,7 +333,7 @@ public function makeAttributes(): void foreach ($combinations as $c) { $attributeId = $c['id_product_attribute']; $priceToConvert = Tools::convertPrice($c['price'], $this->context->currency); - $price = $this->context->getCurrentLocale()->formatPrice($priceToConvert, $this->context->currency->iso_code); + $price = Tools::getContextLocale($this->context)->formatPrice($priceToConvert, $this->context->currency->iso_code); if (array_key_exists($attributeId, $combArray)) { $combArray[$attributeId]['attributes'][$c['group_name']] = [ $c['group_name'], diff --git a/config/checkmd5.csv b/config/checkmd5.csv index 40cb3256..ce61271c 100644 --- a/config/checkmd5.csv +++ b/config/checkmd5.csv @@ -2,7 +2,7 @@ /fr.php|e33982ba5b5cff100bd3f7ea7e8c104b /index.php|be8b25f88c14bddd7711e4585ebae316 /it.php|f7bf9029ec3739108a185666561c2d86 -/lengow.php|7b9a3693b8df26442ef90f87b0c40ea5 +/lengow.php|cf15abe4ac3c55e0e2622a6eca5d550d /loader.php|b3d94d65d0a074088758bc1e50736a01 /config/index.php|be8b25f88c14bddd7711e4585ebae316 /translations/en.csv|81b2e2ef964f1081ff0f455b22a99d42 @@ -22,12 +22,12 @@ /classes/controllers/index.php|a90243841e2e64a4ee2965d4dfa12491 /classes/controllers/LengowFeedController.php|e302aea4c73a2be0c76a4d997b33626f /classes/models/LengowCustomer.php|78579376c21dce9dcea169e642d9802c -/classes/models/LengowHook.php|d5fcd3bb0ce1374e42d5bf836fe0210d +/classes/models/LengowHook.php|60b90ecdb88ea0e7a8c74def8908965a /classes/models/LengowOrderDetail.php|a51019c529e83b2f0eda9e8d713dbd3d -/classes/models/LengowImport.php|9a106938d503900de7807abf00ac9c6f +/classes/models/LengowImport.php|ced1800e7e48502445e9d8f2b884e721 /classes/models/LengowInstall.php|73743387df3e2481d71b7145e039725f /classes/models/LengowConfiguration.php|ad2c80b8f291e56fee5d74f16ab4a958 -/classes/models/LengowMain.php|0073a2254a7e5af9d27e61920ec2ba80 +/classes/models/LengowMain.php|81a6d78f163998b7d3d9a6c22c69886b /classes/models/LengowAction.php|0e51cdaa86b88539c40c7c5273fb8c0d /classes/models/LengowOrder.php|e7d80bb7b25ca35d2d5958ad71aaf26d /classes/models/LengowList.php|071e3d48dfe8f4517374bc57718059b5 @@ -37,7 +37,7 @@ /classes/models/LengowMarketplace.php|e04807c889ca8e8d415a1ae336a1d4c6 /classes/models/LengowMethod.php|fad805cab01bc5ad136066b65e265f3d /classes/models/LengowToolbox.php|0a7e1d3cd33ccaa8948c8c48b1893617 -/classes/models/LengowProduct.php|8d983f5cce6edd00e88474bf4a5b9f72 +/classes/models/LengowProduct.php|9a53599f08f1b931ed462e1887722deb /classes/models/LengowContext.php|af29b1a24c96ee0dbc6f49ff8ad2f812 /classes/models/LengowGender.php|13bcb15e024a66ceb8635ac848a50cc9 /classes/models/LengowPaymentModule.php|5df1a660dd421bcb3dfa7681f5314ec6 @@ -47,7 +47,7 @@ /classes/models/LengowSync.php|0a1a7b2e3922fd50e5768d7846e17175 /classes/models/LengowExport.php|a5e89e32339b8b6d0c84beeff2f5fedb /classes/models/LengowLink.php|2eff889a7fd0197bf87172646d5023e5 -/classes/models/LengowConnector.php|aecd31f4cda8f4ff3f9255eea7a3fc47 +/classes/models/LengowConnector.php|971dded0daf4a19ebc5de46545dec210 /classes/models/LengowTranslation.php|8664ba0942d6ebaee4e66384df308a1f /classes/models/LengowFile.php|b49c051be110d6dd977826d9c5076fea /classes/models/LengowAddress.php|59d6f28bc5dfc1ba4582a416564785e5 @@ -65,7 +65,7 @@ /classes/index.php|a90243841e2e64a4ee2965d4dfa12491 /controllers/front/toolbox.php|a2cd0079e8f9dd10299f23d168ac8415 /controllers/front/cron.php|68e3491c3707d292ad012e36cc64f657 -/controllers/front/export.php|0c600ca5a4482386b54256594ca46927 +/controllers/front/export.php|e01edb71f72fbda565f761185630d4e6 /controllers/front/index.php|32ed9f6c9b16b5f98fb812d3feb7e086 /controllers/index.php|be8b25f88c14bddd7711e4585ebae316 /mails/nl/report.txt|de4160ab037db7fa1806b1dabe546a60 @@ -96,7 +96,9 @@ /mails/fr/report.txt|de4160ab037db7fa1806b1dabe546a60 /mails/fr/index.php|be8b25f88c14bddd7711e4585ebae316 /mails/fr/report.html|aa21eced7789f09a68ca474b04cc431e +/upgrade/update_3.10.0.php|ee99f49182e8939fc8c72e1fdb01d499 /upgrade/update_3.0.1.php|715cedb6c2f1d9651e84ea2a6b54939d +/upgrade/update_3.9.5.php|f5317cafcfffeaa7fdd8e325e9245245 /upgrade/update_3.0.2.php|ee99924a6b556bd82ee52f7966f45bac /upgrade/update_3.7.1.php|ce9aab786524b099812b619237f950df /upgrade/update_3.7.0.php|ce9aab786524b099812b619237f950df @@ -409,7 +411,7 @@ /views/js/lengow/home.js|1f2e8c28ae870b3476483d3759f76964 /views/js/lengow/admin.js|62eeab452a15d83278e4d0c6dcdc50a1 /views/js/lengow/main_setting.js|9489a296dc8ed80847c5990e1a6559f9 -/views/js/lengow/order.js|34baabbff928d0e1dcd7a76c3fabe9a2 +/views/js/lengow/order.js|a0fc7953c8fa47b0436139fe9d966679 /views/js/lengow/feed.js|e9fee6a905dff98bedd0d3599f5fa230 /views/js/lengow/index.php|be8b25f88c14bddd7711e4585ebae316 /views/js/jquery.1.12.0.min.js|e63f1452800f328881a789956054aca3 @@ -490,7 +492,4 @@ /views/css/lengow-pages.css|b4ed4b364d8036bfb4d889649481baf8 /views/css/index.php|be8b25f88c14bddd7711e4585ebae316 /views/index.php|be8b25f88c14bddd7711e4585ebae316 -/webservice/toolbox.php|066445fd095dcf90a833578543252462 -/webservice/cron.php|00c3b6dc78e8dd64b0060cf6c622b58b -/webservice/export.php|dce7218ca28ac22dc6c65d295bf634ee /webservice/index.php|be8b25f88c14bddd7711e4585ebae316 diff --git a/controllers/front/export.php b/controllers/front/export.php index 327ec977..22b4bf40 100644 --- a/controllers/front/export.php +++ b/controllers/front/export.php @@ -191,6 +191,11 @@ public function initContent(): void if ($languageId === 0) { $languageId = LengowContext::getContext()->language->id; } + } elseif (Tools::getIsset(LengowExport::PARAM_LANGUAGE_ID)) { + $languageId = (int) Tools::getValue(LengowExport::PARAM_LANGUAGE_ID); + if (!Language::getLanguage($languageId)) { + $languageId = LengowContext::getContext()->language->id; + } } else { $languageId = LengowContext::getContext()->language->id; } diff --git a/lengow.php b/lengow.php index 13616f33..e6dab280 100755 --- a/lengow.php +++ b/lengow.php @@ -50,7 +50,7 @@ public function __construct() { $this->name = 'lengow'; $this->tab = 'export'; - $this->version = '3.9.4'; // x-release-please-version + $this->version = '3.10.0'; // x-release-please-version $this->author = 'Lengow'; $this->module_key = '__LENGOW_PRESTASHOP_PRODUCT_KEY__'; $this->ps_versions_compliancy = [ @@ -192,6 +192,48 @@ public function reset(): bool return $isReset; } + /** + * Register legacy webservice URLs as PS-native routes pointing to the FO controllers. + * + * Old URLs (modules/lengow/webservice/*.php) still work because: + * - The physical PHP files no longer exist, so Apache forwards to index.php + * - PS Dispatcher picks up these routes and dispatches to the FO controllers + * + * @return array> + */ + public function hookModuleRoutes(): array + { + return [ + 'lengow-cron' => [ + 'controller' => 'cron', + 'rule' => 'modules/lengow/webservice/cron.php', + 'keywords' => [], + 'params' => [ + 'fc' => 'module', + 'module' => 'lengow', + ], + ], + 'lengow-export' => [ + 'controller' => 'export', + 'rule' => 'modules/lengow/webservice/export.php', + 'keywords' => [], + 'params' => [ + 'fc' => 'module', + 'module' => 'lengow', + ], + ], + 'lengow-toolbox' => [ + 'controller' => 'toolbox', + 'rule' => 'modules/lengow/webservice/toolbox.php', + 'keywords' => [], + 'params' => [ + 'fc' => 'module', + 'module' => 'lengow', + ], + ], + ]; + } + /** * Hook to display the icon * diff --git a/views/js/lengow/order.js b/views/js/lengow/order.js index 5c57b4f2..78666f48 100755 --- a/views/js/lengow/order.js +++ b/views/js/lengow/order.js @@ -163,7 +163,7 @@ $.getJSON(href, data, function(content) { lengow_jquery("#lengow_wrapper_messages").html(content['message']); lengow_jquery("#lengow_warning_message").html(content['warning_message']); - lengow_jquery("#lengow_last_importation").text(content['last_importation']); + lengow_jquery("#lengow_last_importation").html(content['last_importation']); lengow_jquery("#lengow_import_orders").html(content['import_orders']); lengow_jquery("#lengow_order_table_wrapper").html(content['list_order']); if (content['show_carrier_notification']) { diff --git a/webservice/cron.php b/webservice/cron.php deleted file mode 100755 index aca9292a..00000000 --- a/webservice/cron.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Lengow SAS - * @license http://www.apache.org/licenses/LICENSE-2.0 - * - * Backward-compatible entry point. Kept so the legacy URL - * modules/lengow/webservice/cron.php still works in PS 8.2+/9.0 without - * any HTTP redirect: bootstraps PS and dispatches to the FO controller. - */ -if (!defined('_PS_VERSION_')) { - exit; -} - -$_GET['fc'] = 'module'; -$_GET['module'] = 'lengow'; -$_GET['controller'] = 'cron'; - -chdir(dirname(__FILE__, 4)); -require 'index.php'; diff --git a/webservice/export.php b/webservice/export.php deleted file mode 100755 index 16f17de2..00000000 --- a/webservice/export.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2017 Lengow SAS - * @license http://www.apache.org/licenses/LICENSE-2.0 - * - * Backward-compatible entry point. Kept so the legacy URL - * modules/lengow/webservice/export.php still works in PS 8.2+/9.0 without - * any HTTP redirect: bootstraps PS and dispatches to the FO controller. - */ -if (!defined('_PS_VERSION_')) { - exit; -} -$_GET['fc'] = 'module'; -$_GET['module'] = 'lengow'; -$_GET['controller'] = 'export'; -chdir(dirname(__FILE__, 4)); -require 'index.php'; diff --git a/webservice/toolbox.php b/webservice/toolbox.php deleted file mode 100644 index 1cf32092..00000000 --- a/webservice/toolbox.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2021 Lengow SAS - * @license http://www.apache.org/licenses/LICENSE-2.0 - * - * Backward-compatible entry point. Kept so the legacy URL - * modules/lengow/webservice/toolbox.php still works in PS 8.2+/9.0 without - * any HTTP redirect: bootstraps PS and dispatches to the FO controller. - */ -if (!defined('_PS_VERSION_')) { - exit; -} -$_GET['fc'] = 'module'; -$_GET['module'] = 'lengow'; -$_GET['controller'] = 'toolbox'; -chdir(dirname(__FILE__, 4)); -require 'index.php'; From 2d5678e66e59cdf022bd8f5a182ff13e5dc6d997 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Fri, 20 Mar 2026 11:04:29 +0100 Subject: [PATCH 39/51] admin page title translations --- src/Controller/Admin/AbstractLengowAdminController.php | 6 +++++- src/Controller/Admin/LengowDashboardAdminController.php | 5 +++++ src/Controller/Admin/LengowFeedAdminController.php | 5 +++++ src/Controller/Admin/LengowHelpAdminController.php | 5 +++++ src/Controller/Admin/LengowHomeAdminController.php | 5 +++++ src/Controller/Admin/LengowLegalsAdminController.php | 5 +++++ src/Controller/Admin/LengowMainSettingAdminController.php | 5 +++++ src/Controller/Admin/LengowOrderAdminController.php | 5 +++++ src/Controller/Admin/LengowOrderSettingAdminController.php | 5 +++++ src/Controller/Admin/LengowToolboxAdminController.php | 5 +++++ 10 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Controller/Admin/AbstractLengowAdminController.php b/src/Controller/Admin/AbstractLengowAdminController.php index d563fc18..dc94d517 100644 --- a/src/Controller/Admin/AbstractLengowAdminController.php +++ b/src/Controller/Admin/AbstractLengowAdminController.php @@ -46,6 +46,7 @@ class_alias( abstract class AbstractLengowAdminController extends PrestaShopAdminController { + abstract protected function getPageTitle(): string; protected \Context $legacyContext; public function __construct( @@ -97,7 +98,10 @@ protected function renderLegacyPage(string $template, object $legacyController): $template, array_merge( $legacyController->getTemplateVars(), - ['base_layout' => '@Modules/lengow/views/templates/admin/twig/ps9_base.html.twig'] + [ + 'base_layout' => '@Modules/lengow/views/templates/admin/twig/ps9_base.html.twig', + 'layoutTitle' => $this->getPageTitle(), + ] ) ); } diff --git a/src/Controller/Admin/LengowDashboardAdminController.php b/src/Controller/Admin/LengowDashboardAdminController.php index ca3edcb8..df6d47c2 100644 --- a/src/Controller/Admin/LengowDashboardAdminController.php +++ b/src/Controller/Admin/LengowDashboardAdminController.php @@ -33,6 +33,11 @@ class LengowDashboardAdminController extends AbstractLengowAdminController { + protected function getPageTitle(): string + { + return (new \LengowTranslation($this->legacyContext))->t('tab.dashboard'); + } + #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { diff --git a/src/Controller/Admin/LengowFeedAdminController.php b/src/Controller/Admin/LengowFeedAdminController.php index ec6028e3..0a40347f 100644 --- a/src/Controller/Admin/LengowFeedAdminController.php +++ b/src/Controller/Admin/LengowFeedAdminController.php @@ -33,6 +33,11 @@ class LengowFeedAdminController extends AbstractLengowAdminController { + protected function getPageTitle(): string + { + return (new \LengowTranslation($this->legacyContext))->t('tab.product'); + } + #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { diff --git a/src/Controller/Admin/LengowHelpAdminController.php b/src/Controller/Admin/LengowHelpAdminController.php index abd612f4..d6b9ab50 100644 --- a/src/Controller/Admin/LengowHelpAdminController.php +++ b/src/Controller/Admin/LengowHelpAdminController.php @@ -32,6 +32,11 @@ class LengowHelpAdminController extends AbstractLengowAdminController { + protected function getPageTitle(): string + { + return (new \LengowTranslation($this->legacyContext))->t('tab.help'); + } + #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { diff --git a/src/Controller/Admin/LengowHomeAdminController.php b/src/Controller/Admin/LengowHomeAdminController.php index 040edf55..8cd9d5f8 100644 --- a/src/Controller/Admin/LengowHomeAdminController.php +++ b/src/Controller/Admin/LengowHomeAdminController.php @@ -33,6 +33,11 @@ class LengowHomeAdminController extends AbstractLengowAdminController { + protected function getPageTitle(): string + { + return (new \LengowTranslation($this->legacyContext))->t('tab.home'); + } + #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { diff --git a/src/Controller/Admin/LengowLegalsAdminController.php b/src/Controller/Admin/LengowLegalsAdminController.php index 05a0fffb..e0c7f3ac 100644 --- a/src/Controller/Admin/LengowLegalsAdminController.php +++ b/src/Controller/Admin/LengowLegalsAdminController.php @@ -32,6 +32,11 @@ class LengowLegalsAdminController extends AbstractLengowAdminController { + protected function getPageTitle(): string + { + return (new \LengowTranslation($this->legacyContext))->t('tab.legals'); + } + #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { diff --git a/src/Controller/Admin/LengowMainSettingAdminController.php b/src/Controller/Admin/LengowMainSettingAdminController.php index 2e83d3b9..44e754b2 100644 --- a/src/Controller/Admin/LengowMainSettingAdminController.php +++ b/src/Controller/Admin/LengowMainSettingAdminController.php @@ -32,6 +32,11 @@ class LengowMainSettingAdminController extends AbstractLengowAdminController { + protected function getPageTitle(): string + { + return (new \LengowTranslation($this->legacyContext))->t('tab.main_setting'); + } + #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { diff --git a/src/Controller/Admin/LengowOrderAdminController.php b/src/Controller/Admin/LengowOrderAdminController.php index 943f58b0..0285e02f 100644 --- a/src/Controller/Admin/LengowOrderAdminController.php +++ b/src/Controller/Admin/LengowOrderAdminController.php @@ -33,6 +33,11 @@ class LengowOrderAdminController extends AbstractLengowAdminController { + protected function getPageTitle(): string + { + return (new \LengowTranslation($this->legacyContext))->t('tab.order'); + } + #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { diff --git a/src/Controller/Admin/LengowOrderSettingAdminController.php b/src/Controller/Admin/LengowOrderSettingAdminController.php index 5e9f475e..3778b15b 100644 --- a/src/Controller/Admin/LengowOrderSettingAdminController.php +++ b/src/Controller/Admin/LengowOrderSettingAdminController.php @@ -32,6 +32,11 @@ class LengowOrderSettingAdminController extends AbstractLengowAdminController { + protected function getPageTitle(): string + { + return (new \LengowTranslation($this->legacyContext))->t('tab.order_setting'); + } + #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { diff --git a/src/Controller/Admin/LengowToolboxAdminController.php b/src/Controller/Admin/LengowToolboxAdminController.php index e60afa01..95778efc 100644 --- a/src/Controller/Admin/LengowToolboxAdminController.php +++ b/src/Controller/Admin/LengowToolboxAdminController.php @@ -32,6 +32,11 @@ class LengowToolboxAdminController extends AbstractLengowAdminController { + protected function getPageTitle(): string + { + return (new \LengowTranslation($this->legacyContext))->t('tab.toolbox'); + } + #[AdminSecurity("is_granted('read', request.get('_legacy_controller'))")] public function indexAction(Request $request): Response { From 3e4ae7e54550f3ad036cbfa7e30c84fcbdfd7c1f Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Fri, 20 Mar 2026 11:40:11 +0100 Subject: [PATCH 40/51] fix install status --- classes/models/LengowInstall.php | 1 + lengow.php | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/classes/models/LengowInstall.php b/classes/models/LengowInstall.php index 363482d5..607ffb7d 100755 --- a/classes/models/LengowInstall.php +++ b/classes/models/LengowInstall.php @@ -203,6 +203,7 @@ public function install(): bool ); $oldVersion = LengowConfiguration::getGlobalValue(LengowConfiguration::PLUGIN_VERSION); $oldVersion = $oldVersion ?: false; + self::setInstallationStatus(false); $this->setDefaultValues(); $this->update($oldVersion); LengowMain::log( diff --git a/lengow.php b/lengow.php index e6dab280..f11a1bb0 100755 --- a/lengow.php +++ b/lengow.php @@ -77,11 +77,12 @@ public function __construct() ); if ($oldVersion !== $this->version) { $this->installClass->clearCaches(); + LengowInstall::setInstallationStatus(false); + $this->installClass->update($oldVersion); LengowConfiguration::updateGlobalValue( LengowConfiguration::PLUGIN_VERSION, $this->version ); - $this->installClass->update($oldVersion); $this->installClass->clearCaches(); } } @@ -104,9 +105,7 @@ public function getContent(): void $router = $sfContainer->get('router'); try { Tools::redirectAdmin($router->generate('lengow_home')); - } catch (\Symfony\Component\Routing\Exception\RouteNotFoundException $e) { - // Routing cache was built before this module was registered (race condition on install). - // Clear it so the next request rebuilds it with the correct routes. + } catch (Symfony\Component\Routing\Exception\RouteNotFoundException $e) { $this->clearCompiledCache(); Tools::redirectAdmin( $this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name]) From 6dcb5e568ae8bd74eea870faa58f1e202c8eeb54 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Mon, 23 Mar 2026 17:11:25 +0100 Subject: [PATCH 41/51] fix lengow backup --- classes/models/LengowBackup.php | 2 +- config/checkmd5.csv | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/classes/models/LengowBackup.php b/classes/models/LengowBackup.php index 10bfb7dd..494b5510 100755 --- a/classes/models/LengowBackup.php +++ b/classes/models/LengowBackup.php @@ -50,7 +50,7 @@ public function add(): bool $rand = dechex(mt_rand(0, min(0xFFFFFFFF, mt_getrandmax()))); $date = time(); $backupFile = $this->getRealBackupPath() . $date . '-lengowbackup' . $rand . '.sql'; - if (!LengowMain::isPathAllowed($backupFile, _PS_MODULE_LENGOW_DIR_)) { + if (!LengowMain::isPathAllowed($backupFile, $this->getRealBackupPath())) { return false; } // figure out what compression is available and open the file diff --git a/config/checkmd5.csv b/config/checkmd5.csv index ce61271c..2bdc1430 100644 --- a/config/checkmd5.csv +++ b/config/checkmd5.csv @@ -2,7 +2,7 @@ /fr.php|e33982ba5b5cff100bd3f7ea7e8c104b /index.php|be8b25f88c14bddd7711e4585ebae316 /it.php|f7bf9029ec3739108a185666561c2d86 -/lengow.php|cf15abe4ac3c55e0e2622a6eca5d550d +/lengow.php|5575dfe830378c1bcdde5d56ac0e7187 /loader.php|b3d94d65d0a074088758bc1e50736a01 /config/index.php|be8b25f88c14bddd7711e4585ebae316 /translations/en.csv|81b2e2ef964f1081ff0f455b22a99d42 @@ -25,7 +25,7 @@ /classes/models/LengowHook.php|60b90ecdb88ea0e7a8c74def8908965a /classes/models/LengowOrderDetail.php|a51019c529e83b2f0eda9e8d713dbd3d /classes/models/LengowImport.php|ced1800e7e48502445e9d8f2b884e721 -/classes/models/LengowInstall.php|73743387df3e2481d71b7145e039725f +/classes/models/LengowInstall.php|7815d2c8b3ed41d4f169df93555d10ac /classes/models/LengowConfiguration.php|ad2c80b8f291e56fee5d74f16ab4a958 /classes/models/LengowMain.php|81a6d78f163998b7d3d9a6c22c69886b /classes/models/LengowAction.php|0e51cdaa86b88539c40c7c5273fb8c0d @@ -58,7 +58,7 @@ /classes/models/LengowException.php|8beecbf00b5c1c047ee19af552903439 /classes/models/LengowCarrier.php|b8d4a25d11201a71fb48bfb6ab5d9222 /classes/models/index.php|a90243841e2e64a4ee2965d4dfa12491 -/classes/models/LengowBackup.php|bb445cc14ac845d657a5bb23eb8bccd4 +/classes/models/LengowBackup.php|5e5baf9145d919f8c0fd43990b883315 /classes/models/LengowCart.php|9e369126c3fd70bf168f962fc6aa50f6 /classes/models/LengowCountry.php|d842caedcd144ae3a02144958804176c /classes/models/LengowShop.php|988978cd8bbf3d7c47f41a91069811d9 @@ -96,9 +96,7 @@ /mails/fr/report.txt|de4160ab037db7fa1806b1dabe546a60 /mails/fr/index.php|be8b25f88c14bddd7711e4585ebae316 /mails/fr/report.html|aa21eced7789f09a68ca474b04cc431e -/upgrade/update_3.10.0.php|ee99f49182e8939fc8c72e1fdb01d499 /upgrade/update_3.0.1.php|715cedb6c2f1d9651e84ea2a6b54939d -/upgrade/update_3.9.5.php|f5317cafcfffeaa7fdd8e325e9245245 /upgrade/update_3.0.2.php|ee99924a6b556bd82ee52f7966f45bac /upgrade/update_3.7.1.php|ce9aab786524b099812b619237f950df /upgrade/update_3.7.0.php|ce9aab786524b099812b619237f950df From 37fc862b76dd81b0d8bdf95feb84aa737ed4df48 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Mon, 23 Mar 2026 17:51:34 +0100 Subject: [PATCH 42/51] legacy links --- classes/models/LengowMain.php | 24 ++++++------------------ config/checkmd5.csv | 2 +- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/classes/models/LengowMain.php b/classes/models/LengowMain.php index cc387998..5b8072e7 100755 --- a/classes/models/LengowMain.php +++ b/classes/models/LengowMain.php @@ -1003,14 +1003,8 @@ public static function getLogInstance(): LengowLog|false */ public static function getExportUrl(?int $idShop = null): string { - return LengowContext::getContext()->link->getModuleLink( - 'lengow', - 'export', - [LengowExport::PARAM_TOKEN => self::getToken($idShop)], - null, - null, - $idShop - ); + return self::getLengowBaseUrl($idShop) . 'webservice/export.php?' + . LengowExport::PARAM_TOKEN . '=' . self::getToken($idShop); } /** @@ -1020,11 +1014,8 @@ public static function getExportUrl(?int $idShop = null): string */ public static function getCronUrl(): string { - return LengowContext::getContext()->link->getModuleLink( - 'lengow', - 'cron', - [LengowImport::PARAM_TOKEN => self::getToken()] - ); + return self::getLengowBaseUrl() . 'webservice/cron.php?' + . LengowImport::PARAM_TOKEN . '=' . self::getToken(); } /** @@ -1034,11 +1025,8 @@ public static function getCronUrl(): string */ public static function getToolboxUrl(): string { - return LengowContext::getContext()->link->getModuleLink( - 'lengow', - 'toolbox', - [LengowToolbox::PARAM_TOKEN => self::getToken()] - ); + return self::getLengowBaseUrl() . 'webservice/toolbox.php?' + . LengowToolbox::PARAM_TOKEN . '=' . self::getToken(); } /** diff --git a/config/checkmd5.csv b/config/checkmd5.csv index 2bdc1430..eda3d1e0 100644 --- a/config/checkmd5.csv +++ b/config/checkmd5.csv @@ -27,7 +27,7 @@ /classes/models/LengowImport.php|ced1800e7e48502445e9d8f2b884e721 /classes/models/LengowInstall.php|7815d2c8b3ed41d4f169df93555d10ac /classes/models/LengowConfiguration.php|ad2c80b8f291e56fee5d74f16ab4a958 -/classes/models/LengowMain.php|81a6d78f163998b7d3d9a6c22c69886b +/classes/models/LengowMain.php|a00a97e28d7224b4f1cc5677585c3978 /classes/models/LengowAction.php|0e51cdaa86b88539c40c7c5273fb8c0d /classes/models/LengowOrder.php|e7d80bb7b25ca35d2d5958ad71aaf26d /classes/models/LengowList.php|071e3d48dfe8f4517374bc57718059b5 From 4f2b8522203f25dc45c08214ea3e0b2e3b04008d Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Wed, 25 Mar 2026 10:54:56 +0100 Subject: [PATCH 43/51] fix tmp return in LengowImport --- classes/models/LengowImport.php | 1 - config/checkmd5.csv | 2 +- tools/vars.enc | Bin 295 -> 295 bytes 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/classes/models/LengowImport.php b/classes/models/LengowImport.php index b87b97e0..68395490 100755 --- a/classes/models/LengowImport.php +++ b/classes/models/LengowImport.php @@ -557,7 +557,6 @@ private function canExecuteSynchronization(): bool $globalError = false; // checks if the process can start if (!$this->debugMode && !$this->importOneOrder && self::isInProcess()) { - return true; // FIXME $globalError = LengowMain::setLogMessage( 'lengow_log.error.rest_time_to_import', ['rest_time' => self::restTimeToImport()] diff --git a/config/checkmd5.csv b/config/checkmd5.csv index eda3d1e0..231839d3 100644 --- a/config/checkmd5.csv +++ b/config/checkmd5.csv @@ -24,7 +24,7 @@ /classes/models/LengowCustomer.php|78579376c21dce9dcea169e642d9802c /classes/models/LengowHook.php|60b90ecdb88ea0e7a8c74def8908965a /classes/models/LengowOrderDetail.php|a51019c529e83b2f0eda9e8d713dbd3d -/classes/models/LengowImport.php|ced1800e7e48502445e9d8f2b884e721 +/classes/models/LengowImport.php|9a106938d503900de7807abf00ac9c6f /classes/models/LengowInstall.php|7815d2c8b3ed41d4f169df93555d10ac /classes/models/LengowConfiguration.php|ad2c80b8f291e56fee5d74f16ab4a958 /classes/models/LengowMain.php|a00a97e28d7224b4f1cc5677585c3978 diff --git a/tools/vars.enc b/tools/vars.enc index 8aeb7de82d1c02945fa88f9f28205035e3fc0a3d..e2c7db7952d874387ce50f16534c252a8f5008f9 100644 GIT binary patch literal 295 zcmV+?0oeYG4Fm}T3g4Bb2Xu|HqyN&tRRQ}}g5)u}wh6He7HR}m3zcX$Uk03*nkLw5 zy6ZRR0Wg&4Vg=A+u=hlHPH*2Uk3gTL*M;GI{vON?U>yCLS|-INBM<}FC+ua1#5(f4 z>!1aZPdGjSD>$Mo^l~uWya{{C)*h@|N-aU=RAcH0D^=5p4?JQ9ZhCMI1b;~%{tGQk zbj)&q0d+IxL}IaJSOBgZu0Km#D-XuXOAC0A^!gg+Q_S5Jq-M?cV|4R( tl%>&i`m(-pf3uOi@cZk;AF~E@+7C9j!$HiIciIV^T literal 295 zcmV+?0oeYG4Fm}T3W(ZK&ALVZH2>1TRRM>*oLT)#@z>+TzyXv1tM_yG)wJY?Mz- zr55^@=%+}zpnt~I#M_ggG)%ct*y{+2?JFrnIbm3rj`tOQq!Ubu*v#`cfaonIv&`vw zb})YMTvsr63=`chE?Kf+aqtrawvoosr#hQkaxF{H`E5SKNPsd3Rv{S;PEXI}{fA=1 thsY$gcDEe@`Pk42Dj(Wf_rK!}qclBj#i8GK!fYy0R9^cjs$hugI29p6k(>Yk From 914a09cad6ea653054581a4851dd49e79e275e9d Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Wed, 25 Mar 2026 15:39:10 +0100 Subject: [PATCH 44/51] backward compatibility for v8.0.0 --- classes/models/LengowMarketplace.php | 5 +++ config/admin/services.yml | 50 ++++++++++++++++++++++------ config/checkmd5.csv | 4 +-- lengow.php | 2 +- 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/classes/models/LengowMarketplace.php b/classes/models/LengowMarketplace.php index 3f3e03d3..1929687f 100644 --- a/classes/models/LengowMarketplace.php +++ b/classes/models/LengowMarketplace.php @@ -551,10 +551,15 @@ protected function getAllParams(string $action, LengowOrder $lengowOrder, array case LengowAction::ARG_DELIVERY_DATE: $params[$arg] = date(LengowMain::DATE_ISO_8601); break; + case LengowAction::ARG_REFUND_REASON: case LengowAction::ARG_REASON: $params[$arg] = $lengowOrder->getRefundReasonByPrestashopId((int) $lengowOrder->lengowId) ?? $this->getDefaultValue((string) $arg); break; + case LengowAction::ARG_REFUND_MODE: + $params[$arg] = $lengowOrder->getRefundModeByPrestashopId((int) $lengowOrder->lengowId) + ?? $this->getDefaultValue((string) $arg); + break; default: if (isset($actions['optional_args']) && in_array($arg, $actions['optional_args'], true)) { break; diff --git a/config/admin/services.yml b/config/admin/services.yml index 112687c3..e1f1e58e 100644 --- a/config/admin/services.yml +++ b/config/admin/services.yml @@ -3,14 +3,44 @@ services: public: false autowire: true autoconfigure: true + bind: + 'PrestaShop\PrestaShop\Adapter\LegacyContext $legacyContext': '@prestashop.adapter.legacy.context' - PrestaShop\Module\Lengow\Controller\Admin\LengowHomeAdminController: ~ - PrestaShop\Module\Lengow\Controller\Admin\LengowDashboardAdminController: ~ - PrestaShop\Module\Lengow\Controller\Admin\LengowFeedAdminController: ~ - PrestaShop\Module\Lengow\Controller\Admin\LengowOrderAdminController: ~ - PrestaShop\Module\Lengow\Controller\Admin\LengowOrderSettingAdminController: ~ - PrestaShop\Module\Lengow\Controller\Admin\LengowMainSettingAdminController: ~ - PrestaShop\Module\Lengow\Controller\Admin\LengowHelpAdminController: ~ - PrestaShop\Module\Lengow\Controller\Admin\LengowLegalsAdminController: ~ - PrestaShop\Module\Lengow\Controller\Admin\LengowToolboxAdminController: ~ - PrestaShop\Module\Lengow\Service\OrderRefundDataUpdater: ~ + PrestaShop\Module\Lengow\Controller\Admin\LengowHomeAdminController: + class: PrestaShop\Module\Lengow\Controller\Admin\LengowHomeAdminController + public: true + tags: ['controller.service_arguments'] + PrestaShop\Module\Lengow\Controller\Admin\LengowDashboardAdminController: + class: PrestaShop\Module\Lengow\Controller\Admin\LengowDashboardAdminController + public: true + tags: ['controller.service_arguments'] + PrestaShop\Module\Lengow\Controller\Admin\LengowFeedAdminController: + class: PrestaShop\Module\Lengow\Controller\Admin\LengowFeedAdminController + public: true + tags: ['controller.service_arguments'] + PrestaShop\Module\Lengow\Controller\Admin\LengowOrderAdminController: + class: PrestaShop\Module\Lengow\Controller\Admin\LengowOrderAdminController + public: true + tags: ['controller.service_arguments'] + PrestaShop\Module\Lengow\Controller\Admin\LengowOrderSettingAdminController: + class: PrestaShop\Module\Lengow\Controller\Admin\LengowOrderSettingAdminController + public: true + tags: ['controller.service_arguments'] + PrestaShop\Module\Lengow\Controller\Admin\LengowMainSettingAdminController: + class: PrestaShop\Module\Lengow\Controller\Admin\LengowMainSettingAdminController + public: true + tags: ['controller.service_arguments'] + PrestaShop\Module\Lengow\Controller\Admin\LengowHelpAdminController: + class: PrestaShop\Module\Lengow\Controller\Admin\LengowHelpAdminController + public: true + tags: ['controller.service_arguments'] + PrestaShop\Module\Lengow\Controller\Admin\LengowLegalsAdminController: + class: PrestaShop\Module\Lengow\Controller\Admin\LengowLegalsAdminController + public: true + tags: ['controller.service_arguments'] + PrestaShop\Module\Lengow\Controller\Admin\LengowToolboxAdminController: + class: PrestaShop\Module\Lengow\Controller\Admin\LengowToolboxAdminController + public: true + tags: ['controller.service_arguments'] + PrestaShop\Module\Lengow\Service\OrderRefundDataUpdater: + class: PrestaShop\Module\Lengow\Service\OrderRefundDataUpdater diff --git a/config/checkmd5.csv b/config/checkmd5.csv index 231839d3..cf95299f 100644 --- a/config/checkmd5.csv +++ b/config/checkmd5.csv @@ -2,7 +2,7 @@ /fr.php|e33982ba5b5cff100bd3f7ea7e8c104b /index.php|be8b25f88c14bddd7711e4585ebae316 /it.php|f7bf9029ec3739108a185666561c2d86 -/lengow.php|5575dfe830378c1bcdde5d56ac0e7187 +/lengow.php|2d60c92ffd1c3eb707350f292c431e9e /loader.php|b3d94d65d0a074088758bc1e50736a01 /config/index.php|be8b25f88c14bddd7711e4585ebae316 /translations/en.csv|81b2e2ef964f1081ff0f455b22a99d42 @@ -34,7 +34,7 @@ /classes/models/LengowOrderCarrier.php|130bddda8e7a344fc2153cb1d55b58f3 /classes/models/LengowOrderError.php|7ab270578749382990d67e7dcc3c3d50 /classes/models/LengowImportOrder.php|1aedede7194e7c832405f86eb7451902 -/classes/models/LengowMarketplace.php|e04807c889ca8e8d415a1ae336a1d4c6 +/classes/models/LengowMarketplace.php|a2175dbe84b063c5097745e13dacb025 /classes/models/LengowMethod.php|fad805cab01bc5ad136066b65e265f3d /classes/models/LengowToolbox.php|0a7e1d3cd33ccaa8948c8c48b1893617 /classes/models/LengowProduct.php|9a53599f08f1b931ed462e1887722deb diff --git a/lengow.php b/lengow.php index f11a1bb0..f2b5d386 100755 --- a/lengow.php +++ b/lengow.php @@ -54,7 +54,7 @@ public function __construct() $this->author = 'Lengow'; $this->module_key = '__LENGOW_PRESTASHOP_PRODUCT_KEY__'; $this->ps_versions_compliancy = [ - 'min' => '8.2.0', + 'min' => '8.0.0', 'max' => '9.99.99', ]; From ad39790d6f82ee572c8add65826a2438318bda9f Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Thu, 26 Mar 2026 11:03:35 +0100 Subject: [PATCH 45/51] paymentTop -> displayPaymentTop --- classes/models/LengowHook.php | 2 +- config/checkmd5.csv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/models/LengowHook.php b/classes/models/LengowHook.php index e3bd3395..95e65b50 100755 --- a/classes/models/LengowHook.php +++ b/classes/models/LengowHook.php @@ -64,7 +64,7 @@ public function registerHooks(): bool $lengowHooks = [ // common version 'postUpdateOrderStatus' => '1.4', - 'paymentTop' => '1.4', + 'displayPaymentTop' => '1.4', 'displayAdminOrder' => '1.4', 'actionOrderStatusUpdate' => '1.4', 'orderConfirmation' => '1.4', diff --git a/config/checkmd5.csv b/config/checkmd5.csv index cf95299f..62ef0c81 100644 --- a/config/checkmd5.csv +++ b/config/checkmd5.csv @@ -22,7 +22,7 @@ /classes/controllers/index.php|a90243841e2e64a4ee2965d4dfa12491 /classes/controllers/LengowFeedController.php|e302aea4c73a2be0c76a4d997b33626f /classes/models/LengowCustomer.php|78579376c21dce9dcea169e642d9802c -/classes/models/LengowHook.php|60b90ecdb88ea0e7a8c74def8908965a +/classes/models/LengowHook.php|a3606416133a8a31b9584b761617cd04 /classes/models/LengowOrderDetail.php|a51019c529e83b2f0eda9e8d713dbd3d /classes/models/LengowImport.php|9a106938d503900de7807abf00ac9c6f /classes/models/LengowInstall.php|7815d2c8b3ed41d4f169df93555d10ac From b8daad73bfb029253ae81c857d2b35c792f478d4 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Thu, 26 Mar 2026 15:15:04 +0100 Subject: [PATCH 46/51] clean docs & old pre v8.0 code --- README.md | 8 +++--- classes/controllers/LengowFeedController.php | 20 ++++++--------- classes/controllers/LengowOrderController.php | 25 ++++++++----------- classes/models/LengowCarrier.php | 8 +++--- classes/models/LengowConfiguration.php | 2 +- classes/models/LengowHook.php | 6 ++--- classes/models/LengowInstall.php | 2 +- classes/models/LengowLink.php | 10 +------- classes/models/LengowMain.php | 4 +-- dod.md | 8 +++--- 10 files changed, 37 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 1b304e53..4929fd91 100755 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Lengow for PrestaShop -- **Requires at least:** 1.7.7 -- **Tested up to:** 8.1.7 -- **Requires PHP:** 7.4 +- **Requires at least:** 8.0.0 +- **Tested up to:** 9.0.0 +- **Requires PHP:** 8.1 - **Stable tag:** 3.9.4 - **License:** Apache-2.0 - **License URI:** http://www.apache.org/licenses/LICENSE-2.0 @@ -75,7 +75,7 @@ Translations in the plugin are managed via a key system and associated yaml file Start by installing Yaml Parser: - sudo apt-get install php5-dev libyaml-dev + sudo apt-get install php-dev libyaml-dev sudo pecl install yaml To translate the project, use specific key in php code and modify the *.yml files in the directory: `lengow/translations/yml/` diff --git a/classes/controllers/LengowFeedController.php b/classes/controllers/LengowFeedController.php index 28099ab0..40822aeb 100755 --- a/classes/controllers/LengowFeedController.php +++ b/classes/controllers/LengowFeedController.php @@ -572,18 +572,14 @@ public static function displayLink(string $key, string $value, array $item): str $link = new LengowLink(); if ($item['id_product']) { $controller = 'AdminProducts'; - if (version_compare(_PS_VERSION_, '1.7', '<')) { - $href = $link->getAbsoluteAdminLink($controller) . '&updateproduct&id_product=' . $item['id_product']; - } else { - $href = $link->getAdminLink( - $controller, - true, - [ - 'updateproduct' => 1, - 'id_product' => $item['id_product'], - ] - ); - } + $href = $link->getAdminLink( + $controller, + true, + [ + 'updateproduct' => 1, + 'id_product' => $item['id_product'], + ] + ); return '' . htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . ''; } diff --git a/classes/controllers/LengowOrderController.php b/classes/controllers/LengowOrderController.php index 6f0a2636..6d733fc6 100755 --- a/classes/controllers/LengowOrderController.php +++ b/classes/controllers/LengowOrderController.php @@ -896,21 +896,16 @@ private static function getOrderAdminLink(int $idOrder): string { $link = new LengowLink(); try { - if (version_compare(_PS_VERSION_, '1.7.7', '<')) { - $href = $link->getAbsoluteAdminLink('AdminOrders') - . '&vieworder&id_order=' . $idOrder; - } else { - $sfParams = [ - 'orderId' => $idOrder, - ]; - $href = Link::getUrlSmarty( - [ - 'entity' => 'sf', - 'route' => 'admin_orders_view', - 'sf-params' => $sfParams, - ] - ); - } + $sfParams = [ + 'orderId' => $idOrder, + ]; + $href = Link::getUrlSmarty( + [ + 'entity' => 'sf', + 'route' => 'admin_orders_view', + 'sf-params' => $sfParams, + ] + ); } catch (PrestaShopException $e) { $href = '#'; } diff --git a/classes/models/LengowCarrier.php b/classes/models/LengowCarrier.php index 95202c76..2a8df6bb 100755 --- a/classes/models/LengowCarrier.php +++ b/classes/models/LengowCarrier.php @@ -1069,9 +1069,7 @@ public static function getCarrierMarketplaceCode(int $idCountry, int $idMarketpl public static function carrierCompatibility(int $idOrder, int $idCustomer, int $idCart, int $idCarrier, LengowAddress $shippingAddress): int { // get SoColissimo carrier id - $soColissimoCarrierId = _PS_VERSION_ < '1.7' - ? Configuration::get('SOCOLISSIMO_CARRIER_ID') - : Configuration::get('COLISSIMO_CARRIER_ID'); + $soColissimoCarrierId = Configuration::get('COLISSIMO_CARRIER_ID'); if ($idCarrier === (int) $soColissimoCarrierId) { if (!LengowMain::isSoColissimoAvailable()) { return self::COMPATIBILITY_KO; @@ -1129,7 +1127,7 @@ public static function carrierCompatibility(int $idOrder, int $idCustomer, int $ public static function addSoColissimo(int $idCart, int $idCustomer, LengowAddress $shippingAddress): bool { $sep = DIRECTORY_SEPARATOR; - $moduleName = _PS_VERSION_ < '1.7' ? 'socolissimo' : 'colissimo_simplicite'; + $moduleName = 'colissimo_simplicite'; $filePath = _PS_MODULE_DIR_ . $moduleName . $sep . 'classes' . $sep . 'SCFields.php'; $loaded = include_once $filePath; if (!$loaded) { @@ -1170,7 +1168,7 @@ public static function addSoColissimo(int $idCart, int $idCustomer, LengowAddres $params['CEZIPCODE'] = (string) $shippingAddress->postcode; $params['CETOWN'] = (string) $shippingAddress->city; $params['PRPAYS'] = (string) Country::getIsoById($shippingAddress->id_country); - $tableName = _PS_VERSION_ < '1.7' ? 'socolissimo_delivery_info' : 'colissimo_delivery_info'; + $tableName = 'colissimo_delivery_info'; $sql = 'INSERT INTO ' . _DB_PREFIX_ . $tableName . ' (`id_cart`, `id_customer`, diff --git a/classes/models/LengowConfiguration.php b/classes/models/LengowConfiguration.php index d9530b36..4e5791bf 100755 --- a/classes/models/LengowConfiguration.php +++ b/classes/models/LengowConfiguration.php @@ -638,7 +638,7 @@ public static function getKeys(?string $key = null): array * @param int|null $idLang PrestaShop lang id * @param int|null $idShopGroup PrestaShop shop group id * @param int|null $idShop PrestaShop shop id - * @param bool $default default value (compatibility version 1.7) + * @param bool $default default value * * @return mixed */ diff --git a/classes/models/LengowHook.php b/classes/models/LengowHook.php index 95e65b50..73eb3d88 100755 --- a/classes/models/LengowHook.php +++ b/classes/models/LengowHook.php @@ -77,9 +77,9 @@ public function registerHooks(): bool 'displayHome' => '8.0', 'actionOrderStatusPostUpdate' => '8.0', 'actionProductCancel' => '8.0', - // version 1.7.8 — order page tabs - 'displayAdminOrderTabLink' => '1.7', - 'displayAdminOrderTabContent' => '1.7', + // PS 8.0+ — order page tabs + 'displayAdminOrderTabLink' => '8.0', + 'displayAdminOrderTabContent' => '8.0', // PS routing: maps legacy webservice/*.php URLs to the FO controllers 'moduleRoutes' => '1.5', ]; diff --git a/classes/models/LengowInstall.php b/classes/models/LengowInstall.php index 607ffb7d..0ba09aee 100755 --- a/classes/models/LengowInstall.php +++ b/classes/models/LengowInstall.php @@ -194,7 +194,7 @@ public function reset(): bool */ public function install(): bool { - if (version_compare(_PS_VERSION_, '1.7.8.0', '<')) { + if (version_compare(_PS_VERSION_, '8.0.0', '<')) { return false; } LengowMain::log( diff --git a/classes/models/LengowLink.php b/classes/models/LengowLink.php index fadd689d..41170186 100755 --- a/classes/models/LengowLink.php +++ b/classes/models/LengowLink.php @@ -35,16 +35,8 @@ class LengowLink extends LinkCore */ public function getAbsoluteAdminLink(string $controller): string { - $adminPath = Tools::getShopDomainSsl(true, true) . - __PS_BASE_URI__ . Tools::substr(_PS_ADMIN_DIR_, strrpos(_PS_ADMIN_DIR_, '/') + 1); try { - if (_PS_VERSION_ < '1.6') { - $adminPath .= '/index.php?tab=' . $controller . '&token=' . Tools::getAdminTokenLite($controller); - } elseif (_PS_VERSION_ < '1.7') { - $adminPath .= '/' . $this->getAdminLink($controller); - } else { - $adminPath = $this->getAdminLink($controller); - } + $adminPath = $this->getAdminLink($controller); } catch (Exception $e) { return ''; } diff --git a/classes/models/LengowMain.php b/classes/models/LengowMain.php index 5b8072e7..80cae605 100755 --- a/classes/models/LengowMain.php +++ b/classes/models/LengowMain.php @@ -905,8 +905,8 @@ public static function isMondialRelayV3Available(): bool */ public static function isSoColissimoAvailable(): bool { - $moduleName = _PS_VERSION_ < '1.7' ? 'socolissimo' : 'colissimo_simplicite'; - $moduleClassName = _PS_VERSION_ < '1.7' ? 'Socolissimo' : 'Colissimo_simplicite'; + $moduleName = 'colissimo_simplicite'; + $moduleClassName = 'Colissimo_simplicite'; $supportedVersion = '2.8.5'; $sep = DIRECTORY_SEPARATOR; $moduleDir = _PS_MODULE_DIR_ . $moduleName . $sep; diff --git a/dod.md b/dod.md index 9c7c92c3..67586d10 100755 --- a/dod.md +++ b/dod.md @@ -2,8 +2,8 @@ ## Liste des critères ## -* Recetter sa feature sur les versions 1.6 et 1.7 : -* Coder en respectant la version de PHP 5.5 : +* Recetter sa feature sur les versions 8.x et 9.x : +* Coder en respectant la version de PHP 8.1 : * Pas de modification de comportement de fonction : * Principe SOLID (au moins le S) : * Coding Style (PSR2) : @@ -19,10 +19,10 @@ ## Explication des critères ## -### Recetter sa feature sur les versions 1.6 et 1.7 ### +### Recetter sa feature sur les versions 8.x et 9.x ### Tester son développement sur toutes les versions compatibles avec le module -### Coder en respectant la version de PHP 5.5 ### +### Coder en respectant la version de PHP 8.1 ### Coder en respectant tous les standards de la version de PHP requise ### Pas de modification de comportement de fonction ### From 96e5dd36d176f0d04a24141ddb13ddb6d1f6d9aa Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Thu, 26 Mar 2026 15:15:36 +0100 Subject: [PATCH 47/51] remove not used anymore .htaccess --- .htaccess | 58 ------------------------------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 .htaccess diff --git a/.htaccess b/.htaccess deleted file mode 100644 index 77509763..00000000 --- a/.htaccess +++ /dev/null @@ -1,58 +0,0 @@ -# Apache 2.2 - - Order deny,allow - Deny from all - - Allow from all - - - Allow from all - - - Allow from all - - - Allow from all - - - Allow from all - - - Allow from all - - - Allow from all - - - Allow from all - - - -# Apache 2.4 - - Require all denied - - Require all granted - - - Require all granted - - - Require all granted - - - Require all granted - - - Require all granted - - - Require all granted - - - Require all granted - - - Require all granted - - From 9a0066ecb0262b64e6f649358cfc4dbfb200093a Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Fri, 27 Mar 2026 11:35:10 +0100 Subject: [PATCH 48/51] add .htaccess back (avoid 403 on legacy urls) --- .htaccess | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .htaccess diff --git a/.htaccess b/.htaccess new file mode 100644 index 00000000..77509763 --- /dev/null +++ b/.htaccess @@ -0,0 +1,58 @@ +# Apache 2.2 + + Order deny,allow + Deny from all + + Allow from all + + + Allow from all + + + Allow from all + + + Allow from all + + + Allow from all + + + Allow from all + + + Allow from all + + + Allow from all + + + +# Apache 2.4 + + Require all denied + + Require all granted + + + Require all granted + + + Require all granted + + + Require all granted + + + Require all granted + + + Require all granted + + + Require all granted + + + Require all granted + + From a9c1fdc551c7fa6d73659530f83fbc9b0f71fb70 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Fri, 27 Mar 2026 11:44:13 +0100 Subject: [PATCH 49/51] revert back to 3.9.4 (will be updated with release please) --- lengow.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lengow.php b/lengow.php index f2b5d386..378e6d10 100755 --- a/lengow.php +++ b/lengow.php @@ -50,7 +50,7 @@ public function __construct() { $this->name = 'lengow'; $this->tab = 'export'; - $this->version = '3.10.0'; // x-release-please-version + $this->version = '3.9.4'; // x-release-please-version $this->author = 'Lengow'; $this->module_key = '__LENGOW_PRESTASHOP_PRODUCT_KEY__'; $this->ps_versions_compliancy = [ From 51fc2e798f87dea55128a14f35d8c1a1eb453925 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Fri, 27 Mar 2026 14:53:03 +0100 Subject: [PATCH 50/51] fix potentiel hook duplicate error --- classes/models/LengowHook.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/classes/models/LengowHook.php b/classes/models/LengowHook.php index 73eb3d88..578585c7 100755 --- a/classes/models/LengowHook.php +++ b/classes/models/LengowHook.php @@ -89,7 +89,16 @@ public function registerHooks(): bool if ($this->module->isRegisteredInHook($hook)) { continue; } - if (!$this->module->registerHook($hook)) { + try { + $registered = $this->module->registerHook($hook); + } catch (PrestaShopDatabaseException $e) { + LengowMain::log( + LengowLog::CODE_INSTALL, + LengowMain::setLogMessage('log.install.registering_hook_success', ['hook' => $hook]) + ); + continue; + } + if (!$registered) { LengowMain::log( LengowLog::CODE_INSTALL, LengowMain::setLogMessage('log.install.registering_hook_error', ['hook' => $hook]) From 4ecc1c4b6651a35850c6c66baa3aba10c67cc988 Mon Sep 17 00:00:00 2001 From: Arnaud Hours Date: Fri, 27 Mar 2026 15:01:13 +0100 Subject: [PATCH 51/51] fix deprecated curl_close with php8.5 --- classes/models/LengowConnector.php | 1 - config/checkmd5.csv | 20 ++++++++++---------- tools/vars.enc | Bin 295 -> 297 bytes 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/classes/models/LengowConnector.php b/classes/models/LengowConnector.php index c8df0509..718d3f3b 100755 --- a/classes/models/LengowConnector.php +++ b/classes/models/LengowConnector.php @@ -636,7 +636,6 @@ private function makeRequest(string $type, string $api, array $args, ?string $to $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); $curlErrorNumber = curl_errno($ch); - curl_close($ch); $this->checkReturnRequest($result, $httpCode, $curlError, $curlErrorNumber); return $result; diff --git a/config/checkmd5.csv b/config/checkmd5.csv index 62ef0c81..6f0e333b 100644 --- a/config/checkmd5.csv +++ b/config/checkmd5.csv @@ -2,7 +2,7 @@ /fr.php|e33982ba5b5cff100bd3f7ea7e8c104b /index.php|be8b25f88c14bddd7711e4585ebae316 /it.php|f7bf9029ec3739108a185666561c2d86 -/lengow.php|2d60c92ffd1c3eb707350f292c431e9e +/lengow.php|9cb9064a1b9bc18cde5df26212969938 /loader.php|b3d94d65d0a074088758bc1e50736a01 /config/index.php|be8b25f88c14bddd7711e4585ebae316 /translations/en.csv|81b2e2ef964f1081ff0f455b22a99d42 @@ -10,7 +10,7 @@ /translations/fr.csv|a58e1647eaa7fdc493c171860eca27e2 /translations/index.php|be8b25f88c14bddd7711e4585ebae316 /translations/it.csv|8f3106c2c9c88c6b7f40ccb24aec629b -/classes/controllers/LengowOrderController.php|bc5195fc156cb94351f971d92604ccfd +/classes/controllers/LengowOrderController.php|1e4c0b35f3334e69406d9e16c7c70b29 /classes/controllers/LengowDashboardController.php|ebe6a9d71e4a9be250061d96ec23b9ca /classes/controllers/LengowLegalsController.php|14effece7503b9524c83f628d255d146 /classes/controllers/LengowController.php|e4d8bbb3a4d2212e138f8d67dbd1dcd7 @@ -20,14 +20,14 @@ /classes/controllers/LengowOrderSettingController.php|4cd5566fa9340122be65d84ae50d2e63 /classes/controllers/LengowHomeController.php|60caf882f1b38928c27164b913ad4159 /classes/controllers/index.php|a90243841e2e64a4ee2965d4dfa12491 -/classes/controllers/LengowFeedController.php|e302aea4c73a2be0c76a4d997b33626f +/classes/controllers/LengowFeedController.php|41b4db4ac3a070ee3cc599044b51f75d /classes/models/LengowCustomer.php|78579376c21dce9dcea169e642d9802c -/classes/models/LengowHook.php|a3606416133a8a31b9584b761617cd04 +/classes/models/LengowHook.php|7e17d9ebfa664d8689fec493745a3900 /classes/models/LengowOrderDetail.php|a51019c529e83b2f0eda9e8d713dbd3d /classes/models/LengowImport.php|9a106938d503900de7807abf00ac9c6f -/classes/models/LengowInstall.php|7815d2c8b3ed41d4f169df93555d10ac -/classes/models/LengowConfiguration.php|ad2c80b8f291e56fee5d74f16ab4a958 -/classes/models/LengowMain.php|a00a97e28d7224b4f1cc5677585c3978 +/classes/models/LengowInstall.php|be765799d993e72a2656cb2f84f81579 +/classes/models/LengowConfiguration.php|25df6dedabd775a60420e8c263751278 +/classes/models/LengowMain.php|058ddf81649f4a53b93bddefaa6f4129 /classes/models/LengowAction.php|0e51cdaa86b88539c40c7c5273fb8c0d /classes/models/LengowOrder.php|e7d80bb7b25ca35d2d5958ad71aaf26d /classes/models/LengowList.php|071e3d48dfe8f4517374bc57718059b5 @@ -46,8 +46,8 @@ /classes/models/LengowOrderLine.php|34d8c9facb15fe65eae3492cfb0065f8 /classes/models/LengowSync.php|0a1a7b2e3922fd50e5768d7846e17175 /classes/models/LengowExport.php|a5e89e32339b8b6d0c84beeff2f5fedb -/classes/models/LengowLink.php|2eff889a7fd0197bf87172646d5023e5 -/classes/models/LengowConnector.php|971dded0daf4a19ebc5de46545dec210 +/classes/models/LengowLink.php|bdbc53d7f8c0d25ded5203e321c2933c +/classes/models/LengowConnector.php|0746d2e0d7b4de082f5447567392444d /classes/models/LengowTranslation.php|8664ba0942d6ebaee4e66384df308a1f /classes/models/LengowFile.php|b49c051be110d6dd977826d9c5076fea /classes/models/LengowAddress.php|59d6f28bc5dfc1ba4582a416564785e5 @@ -56,7 +56,7 @@ /classes/models/LengowLog.php|36d1d903fedfa5c571134c0af4b63fee /classes/models/LengowCatalog.php|07c15f25bb0905335f9a64a49d318be5 /classes/models/LengowException.php|8beecbf00b5c1c047ee19af552903439 -/classes/models/LengowCarrier.php|b8d4a25d11201a71fb48bfb6ab5d9222 +/classes/models/LengowCarrier.php|550bea36d8b683bc250934a8532529dc /classes/models/index.php|a90243841e2e64a4ee2965d4dfa12491 /classes/models/LengowBackup.php|5e5baf9145d919f8c0fd43990b883315 /classes/models/LengowCart.php|9e369126c3fd70bf168f962fc6aa50f6 diff --git a/tools/vars.enc b/tools/vars.enc index e2c7db7952d874387ce50f16534c252a8f5008f9..8e12171656b0dc069b376b8c757d5325528da28b 100644 GIT binary patch literal 297 zcmV+^0oMME4Fm}T3KIY6vKMOVb^p@9R{<_A>3uc8APT*$q}7tYIO{@hkXJyQ^b%TF zbyRJ|K)@vjqo)o2Xakr7lyA!EL*_xy=kI2Qfzt5dT0$#Uf{goTOly?3;~ouTLs~S_ z)q;bpbkIADV?Rj(vByaDNuwaHw_>Otxr}zpu(p;?=C9-gie+J&COVv@Y#QZ0Y!oia z??cf~0|LhK_e^w0=xGNu+JK!)p}gcl4M8B2J=l5&B4>$?5zSck&S)m)%Grb6L`B?- zQi~NYlz_$hR}I^=-;+0=>iWq&gO|3gez$L$CrL#{!vOV993OwnMX}yrynz-5+Y@?; vaD(w1v(`>4E7voX50`^%r}yCLS|-INBM<}FC+ua1#5(f4 z>!1aZPdGjSD>$Mo^l~uWya{{C)*h@|N-aU=RAcH0D^=5p4?JQ9ZhCMI1b;~%{tGQk zbj)&q0d+IxL}IaJSOBgZu0Km#D-XuXOAC0A^!gg+Q_S5Jq-M?cV|4R( tl%>&i`m(-pf3uOi@cZk;AF~E@+7C9j!$HiIciIV^T