From 403526ae1d61d427ca41b3673f8bb67c68508ef6 Mon Sep 17 00:00:00 2001 From: Alexis Guyomar Date: Mon, 2 Mar 2026 17:15:34 +0100 Subject: [PATCH 01/23] github: new workflow to add issue to project --- .github/workflows/add-issue-to-project.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/add-issue-to-project.yml diff --git a/.github/workflows/add-issue-to-project.yml b/.github/workflows/add-issue-to-project.yml new file mode 100644 index 00000000..cfa4ba3f --- /dev/null +++ b/.github/workflows/add-issue-to-project.yml @@ -0,0 +1,13 @@ +name: Add Issue to Project + +on: + issues: + types: [ opened ] + +jobs: + add-to-project: + uses: PrestaShop/.github/.github/workflows/reusable-add-to-project.yml@master + with: + project-number: 47 + secrets: + TOKEN: ${{ secrets.JARVIS_TOKEN }} From 24a14dd03c9dec14f113c66bd3c98eb4c91b07a5 Mon Sep 17 00:00:00 2001 From: Matthieu Rolland Date: Tue, 7 Jul 2026 16:48:53 +0200 Subject: [PATCH 02/23] improve sql query --- src/Repository/ProductCommentCriterionRepository.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Repository/ProductCommentCriterionRepository.php b/src/Repository/ProductCommentCriterionRepository.php index 6b142af2..4a0e51f5 100644 --- a/src/Repository/ProductCommentCriterionRepository.php +++ b/src/Repository/ProductCommentCriterionRepository.php @@ -159,12 +159,13 @@ public function update(ProductCommentCriterion $criterion): int private function updateCategories($criterion): int { $res = 0; - $criterionId = $criterion->getId(); + $criterionId = (int) $criterion->getId(); foreach ($criterion->getCategories() as $id_category) { $res += $this->connection->executeUpdate( 'INSERT INTO `' . _DB_PREFIX_ . 'product_comment_criterion_category` (`id_product_comment_criterion`, `id_category`) - VALUES(' . $criterionId . ',' . $id_category . ')' + VALUES(?, ?)', + [$criterionId, (int) $id_category] ); } @@ -174,12 +175,13 @@ private function updateCategories($criterion): int private function updateProducts($criterion): int { $res = 0; - $criterionId = $criterion->getId(); + $criterionId = (int) $criterion->getId(); foreach ($criterion->getProducts() as $id_product) { $res += $this->connection->executeUpdate( 'INSERT INTO `' . _DB_PREFIX_ . 'product_comment_criterion_product` (`id_product_comment_criterion`, `id_product`) - VALUES(' . $criterionId . ',' . $id_product . ')' + VALUES(?, ?)', + [$criterionId, (int) $id_product] ); } From 4ea3b141e0439b0d2bbb59f340bb6515b8c50145 Mon Sep 17 00:00:00 2001 From: Hlavtox Date: Thu, 9 Jul 2026 08:14:16 +0200 Subject: [PATCH 03/23] Add new structured data --- config.xml | 4 +- productcomments.php | 116 ++++++++++++++++++++------------------ upgrade/install-8.0.1.php | 33 +++++++++++ 3 files changed, 97 insertions(+), 56 deletions(-) create mode 100644 upgrade/install-8.0.1.php diff --git a/config.xml b/config.xml index 958f4458..b1f5984a 100644 --- a/config.xml +++ b/config.xml @@ -2,11 +2,11 @@ productcomments - + 1 0 - + diff --git a/productcomments.php b/productcomments.php index 851d063c..2b9885ed 100644 --- a/productcomments.php +++ b/productcomments.php @@ -43,11 +43,23 @@ class ProductComments extends Module implements WidgetInterface private $langId; private $shopId; + public const HOOKS = [ + 'displayFooterProduct', + 'displayHeader', + 'displayProductListReviews', + 'displayProductAdditionalInfo', + 'filterProductContent', + 'registerGDPRConsent', + 'actionDeleteGDPRCustomer', + 'actionExportGDPRData', + 'actionFrontControllerSetVariables', + ]; + public function __construct() { $this->name = 'productcomments'; $this->tab = 'front_office_features'; - $this->version = '8.0.0'; + $this->version = '8.0.1'; $this->author = 'PrestaShop'; $this->need_instance = 0; $this->bootstrap = true; @@ -85,66 +97,30 @@ public function install($keep = true) } } - if ( - parent::install() == false || - !$this->registerHook('displayFooterProduct') || //Product page footer - !$this->registerHook('displayHeader') || //Adds css and javascript on front - !$this->registerHook('displayProductListReviews') || //Product list miniature - !$this->registerHook('displayProductAdditionalInfo') || //Display info in checkout column - !$this->registerHook('filterProductContent') || // Add infos to Product page - !$this->registerHook('registerGDPRConsent') || - !$this->registerHook('actionDeleteGDPRCustomer') || - !$this->registerHook('actionExportGDPRData') || - - !Configuration::updateValue('PRODUCT_COMMENTS_MINIMAL_TIME', 30) || - !Configuration::updateValue('PRODUCT_COMMENTS_ALLOW_GUESTS', 0) || - !Configuration::updateValue('PRODUCT_COMMENTS_USEFULNESS', 1) || - !Configuration::updateValue('PRODUCT_COMMENTS_COMMENTS_PER_PAGE', 5) || - !Configuration::updateValue('PRODUCT_COMMENTS_ANONYMISATION', 0) || - !Configuration::updateValue('PRODUCT_COMMENTS_MODERATE', 1) - ) { - return false; - } - - return true; + return parent::install() && $this->registerHook(self::HOOKS) && + Configuration::updateValue('PRODUCT_COMMENTS_MINIMAL_TIME', 30) && + Configuration::updateValue('PRODUCT_COMMENTS_ALLOW_GUESTS', 0) && + Configuration::updateValue('PRODUCT_COMMENTS_USEFULNESS', 1) && + Configuration::updateValue('PRODUCT_COMMENTS_COMMENTS_PER_PAGE', 5) && + Configuration::updateValue('PRODUCT_COMMENTS_ANONYMISATION', 0) && + Configuration::updateValue('PRODUCT_COMMENTS_MODERATE', 1); } public function uninstall($keep = true) { - if ( - !parent::uninstall() || ($keep && !$this->deleteTables()) || - !Configuration::deleteByName('PRODUCT_COMMENTS_MODERATE') || - !Configuration::deleteByName('PRODUCT_COMMENTS_COMMENTS_PER_PAGE') || - !Configuration::deleteByName('PRODUCT_COMMENTS_ANONYMISATION') || - !Configuration::deleteByName('PRODUCT_COMMENTS_ALLOW_GUESTS') || - !Configuration::deleteByName('PRODUCT_COMMENTS_USEFULNESS') || - !Configuration::deleteByName('PRODUCT_COMMENTS_MINIMAL_TIME') || - - !$this->unregisterHook('registerGDPRConsent') || - !$this->unregisterHook('actionDeleteGDPRCustomer') || - !$this->unregisterHook('actionExportGDPRData') || - - !$this->unregisterHook('displayProductAdditionalInfo') || - !$this->unregisterHook('displayHeader') || - !$this->unregisterHook('displayFooterProduct') || - !$this->unregisterHook('displayProductListReviews') - ) { - return false; - } - - return true; + return parent::uninstall() && + ($keep && !$this->deleteTables()) && + Configuration::deleteByName('PRODUCT_COMMENTS_MODERATE') && + Configuration::deleteByName('PRODUCT_COMMENTS_COMMENTS_PER_PAGE') && + Configuration::deleteByName('PRODUCT_COMMENTS_ANONYMISATION') && + Configuration::deleteByName('PRODUCT_COMMENTS_ALLOW_GUESTS') && + Configuration::deleteByName('PRODUCT_COMMENTS_USEFULNESS') && + Configuration::deleteByName('PRODUCT_COMMENTS_MINIMAL_TIME'); } public function reset() { - if (!$this->uninstall(false)) { - return false; - } - if (!$this->install(false)) { - return false; - } - - return true; + return $this->uninstall(false) && $this->install(false); } public function deleteTables() @@ -935,7 +911,7 @@ public function hookDisplayFooterProduct($params) } /** - * Inject data about productcomments in the product object for frontoffice + * Inject data about productcomments in the product object for frontoffice. This is the older way of adding the data before PrestaShop 9.2. * * @param array $params * @@ -1112,4 +1088,36 @@ public function hookRegisterGDPRConsent() at module installation. */ } + + /** + * This hook adds reviews into structured data on PrestaShop 9.2 and newer. + * On lower versions, it doesn't do anything. + */ + public function hookActionFrontControllerSetVariables($params) + { + // Check if the current page is a product page and if structured data for the product is available + if ($this->context->controller->php_self !== 'product' || !isset($params['templateVars']['structured_data']['product'])) { + return; + } + + // Get product ID, check for pages where the product is not loaded (e.g., 404 pages) + $product = $this->context->controller->getProduct(); + if (empty($product) || !Validate::isLoadedObject($product)) { + return; + } + + // Get the rating and append it to the array + $commentRepository = $this->get('product_comment_repository'); + $averageRating = $commentRepository->getAverageGrade($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $nbComments = $commentRepository->getCommentsNumber($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); + + $params['templateVars']['structured_data']['product']['aggregateRating'] = [ + '@type' => 'AggregateRating', + 'ratingValue' => $averageRating, + 'reviewCount' => $nbComments, + // Constant values for best and worst rating, as per schema.org specifications, so the bot knows what the scale is. + 'bestRating' => 5, + 'worstRating' => 1, + ]; + } } diff --git a/upgrade/install-8.0.1.php b/upgrade/install-8.0.1.php new file mode 100644 index 00000000..29d2e1bb --- /dev/null +++ b/upgrade/install-8.0.1.php @@ -0,0 +1,33 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) + */ +if (!defined('_PS_VERSION_')) { + exit; +} + +function upgrade_module_8_0_1($object) +{ + return $object->registerHook('actionFrontControllerSetVariables'); +} From 7e1b4943dbad3bd77c45684ed9d1849209e6b3a6 Mon Sep 17 00:00:00 2001 From: Hlavtox Date: Thu, 9 Jul 2026 14:57:36 +0200 Subject: [PATCH 04/23] Do not add empty aggregateRating --- productcomments.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/productcomments.php b/productcomments.php index 2b9885ed..1c2c376e 100644 --- a/productcomments.php +++ b/productcomments.php @@ -1111,6 +1111,11 @@ public function hookActionFrontControllerSetVariables($params) $averageRating = $commentRepository->getAverageGrade($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); $nbComments = $commentRepository->getCommentsNumber($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); + // If no rating or no comments, don't add the structured data + if (empty($averageRating) || empty($nbComments)) { + return; + } + $params['templateVars']['structured_data']['product']['aggregateRating'] = [ '@type' => 'AggregateRating', 'ratingValue' => $averageRating, From c8b682933ce0d661ddc6e4842c54aff66f6df6b6 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Thu, 9 Jul 2026 10:55:16 +0200 Subject: [PATCH 05/23] CI : PHPStan with common action --- .github/workflows/php.yml | 122 ++++++++++++++---- ProductComment.php | 3 - ProductCommentCriterion.php | 1 - config/admin/services.yml | 1 - controllers/front/CommentGrade.php | 18 ++- controllers/front/ListComments.php | 3 +- controllers/front/PostComment.php | 6 +- controllers/front/ReportComment.php | 6 +- controllers/front/UpdateCommentUsefulness.php | 6 +- productcomments.php | 57 +++++--- src/Entity/ProductCommentGrade.php | 9 +- ...ProductCommentCriterionFormDataHandler.php | 9 -- .../ProductCommentCriterionRepository.php | 5 - src/Repository/ProductCommentRepository.php | 5 - tests/{phpstan => php}/index.php | 0 tests/php/phpstan/index.php | 34 +++++ tests/php/phpstan/phpstan-8.2.x.neon | 18 +++ tests/php/phpstan/phpstan-9.0.3.neon | 6 + tests/php/phpstan/phpstan-9.1.x.neon | 6 + tests/php/phpstan/phpstan-develop.neon | 6 + tests/php/phpstan/phpstan.neon | 2 + tests/php/phpstan/prepend-constants.php | 11 ++ tests/phpstan.sh | 28 ---- tests/phpstan/phpstan-1.7.7.neon | 13 -- tests/phpstan/phpstan-1.7.8.neon | 12 -- tests/phpstan/phpstan-8.0.neon | 5 - tests/phpstan/phpstan-latest.neon | 2 - tests/phpstan/phpstan.neon | 16 --- 28 files changed, 249 insertions(+), 161 deletions(-) rename tests/{phpstan => php}/index.php (100%) create mode 100644 tests/php/phpstan/index.php create mode 100644 tests/php/phpstan/phpstan-8.2.x.neon create mode 100644 tests/php/phpstan/phpstan-9.0.3.neon create mode 100644 tests/php/phpstan/phpstan-9.1.x.neon create mode 100644 tests/php/phpstan/phpstan-develop.neon create mode 100644 tests/php/phpstan/phpstan.neon create mode 100644 tests/php/phpstan/prepend-constants.php delete mode 100755 tests/phpstan.sh delete mode 100644 tests/phpstan/phpstan-1.7.7.neon delete mode 100644 tests/phpstan/phpstan-1.7.8.neon delete mode 100644 tests/phpstan/phpstan-8.0.neon delete mode 100644 tests/phpstan/phpstan-latest.neon delete mode 100644 tests/phpstan/phpstan.neon diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 8e08b03f..1175e62b 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -52,38 +52,106 @@ jobs: - name: Run PHP-CS-Fixer run: ./vendor/bin/php-cs-fixer fix --dry-run --diff --using-cache=no - # Run PHPStan against the module and a PrestaShop release - phpstan: - name: PHPStan + # Run PHPStan against the module (PHP 7.4 – PS 8.2) + phpstan-74-81: + name: PHPStan (PHP 7.4 - 8.1) runs-on: ubuntu-latest strategy: matrix: - presta-versions: ['1.7.8', '8.0', 'latest'] + presta_version: ['8.2.x'] + php_version: ['7.4', '8.1'] + fail-fast: false + env: + PHPRC: ${{ github.workspace }}/${{ github.event.repository.name }}/.phpstan-php-ini steps: - - name: Setup PHP - uses: shivammathur/setup-php@v2 + - name: Checkout repository + uses: actions/checkout@v6 with: - php-version: '7.4' - - - name: Checkout - uses: actions/checkout@v4 - - # Add vendor folder in cache to make next builds faster - - name: Cache vendor folder - uses: actions/cache@v4 + path: ${{ github.event.repository.name }} + + - name: Prepare PHP env for PrestaShop 8 (define constants before any bootstrap) + run: | + mkdir -p ${{ github.event.repository.name }}/.phpstan-php-ini + { + echo "auto_prepend_file=$GITHUB_WORKSPACE/${{ github.event.repository.name }}/tests/php/phpstan/prepend-constants.php" + echo "memory_limit=512M" + } > ${{ github.event.repository.name }}/.phpstan-php-ini/php.ini + + - name: Run PHPStan + uses: PrestaShop/.github/.github/actions/php-ci/phpstan@master with: - path: vendor - key: php-${{ hashFiles('composer.lock') }} - - # Add composer local folder in cache to make next builds faster - - name: Cache composer folder - uses: actions/cache@v4 + php-version: ${{ matrix.php_version }} + presta-version: ${{ matrix.presta_version }} + module-name: ${{ github.event.repository.name }} + phpstan-level: '5' + phpstan-config: tests/php/phpstan/phpstan-${{ matrix.presta_version }}.neon + phpstan-version: '^0.12' + composer-version: '2.2.18' + + # Run PHPStan against the module (PHP 8.1 – 8.4) + phpstan-81-84: + name: PHPStan (PHP 8.1 - 8.4) + runs-on: ubuntu-latest + strategy: + matrix: + presta_version: ['9.0.3'] + php_version: ['8.1', '8.4'] + fail-fast: false + env: + PHPRC: ${{ github.workspace }}/${{ github.event.repository.name }}/.phpstan-php-ini + steps: + - name: Checkout repository + uses: actions/checkout@v6 with: - path: ~/.composer/cache - key: php-composer-cache - - - run: composer install + path: ${{ github.event.repository.name }} + + - name: Prepare PHP env for PrestaShop 9.1.x and later (define constants before any bootstrap) + run: | + mkdir -p ${{ github.event.repository.name }}/.phpstan-php-ini + { + echo "auto_prepend_file=$GITHUB_WORKSPACE/${{ github.event.repository.name }}/tests/php/phpstan/prepend-constants.php" + echo "memory_limit=512M" + } > ${{ github.event.repository.name }}/.phpstan-php-ini/php.ini + + - name: Run PHPStan + uses: PrestaShop/.github/.github/actions/php-ci/phpstan@master + with: + php-version: ${{ matrix.php_version }} + presta-version: ${{ matrix.presta_version }} + module-name: ${{ github.event.repository.name }} + phpstan-level: '5' + phpstan-config: tests/php/phpstan/phpstan-${{ matrix.presta_version }}.neon - # Docker images prestashop/prestashop may be used, even if the shop remains uninstalled - - name: Execute PHPStan on PrestaShop (Tag ${{ matrix.presta-versions }}) - run: ./tests/phpstan.sh ${{ matrix.presta-versions }} + # Run PHPStan against the module (PHP 8.1 – 8.5) + phpstan: + name: PHPStan (PHP 8.1 - 8.5) + runs-on: ubuntu-latest + strategy: + matrix: + presta_version: ['9.1.x', 'develop'] + php_version: ['8.1', '8.5'] + fail-fast: false + env: + PHPRC: ${{ github.workspace }}/${{ github.event.repository.name }}/.phpstan-php-ini + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + path: ${{ github.event.repository.name }} + + - name: Prepare PHP env for PrestaShop 9.1.x and later (define constants before any bootstrap) + run: | + mkdir -p ${{ github.event.repository.name }}/.phpstan-php-ini + { + echo "auto_prepend_file=$GITHUB_WORKSPACE/${{ github.event.repository.name }}/tests/php/phpstan/prepend-constants.php" + echo "memory_limit=512M" + } > ${{ github.event.repository.name }}/.phpstan-php-ini/php.ini + + - name: Run PHPStan + uses: PrestaShop/.github/.github/actions/php-ci/phpstan@master + with: + php-version: ${{ matrix.php_version }} + presta-version: ${{ matrix.presta_version }} + module-name: ${{ github.event.repository.name }} + phpstan-level: '5' + phpstan-config: tests/php/phpstan/phpstan-${{ matrix.presta_version }}.neon \ No newline at end of file diff --git a/ProductComment.php b/ProductComment.php index d9ce2069..d0210b0d 100644 --- a/ProductComment.php +++ b/ProductComment.php @@ -29,9 +29,6 @@ class ProductComment extends ObjectModel { - /** @var int */ - public $id; - /** @var int */ public $id_product; diff --git a/ProductCommentCriterion.php b/ProductCommentCriterion.php index 5caf632c..0eb573d6 100644 --- a/ProductCommentCriterion.php +++ b/ProductCommentCriterion.php @@ -27,7 +27,6 @@ class ProductCommentCriterion extends ObjectModel { const NAME_MAX_LENGTH = 64; - public $id; public $id_product_comment_criterion_type; public $name; public $active = true; diff --git a/config/admin/services.yml b/config/admin/services.yml index 02ce511d..d161f72a 100644 --- a/config/admin/services.yml +++ b/config/admin/services.yml @@ -13,6 +13,5 @@ services: class: 'PrestaShop\Module\ProductComment\Form\ProductCommentCriterionFormDataHandler' public: true arguments: - - '@product_comment_criterion_repository' - '@prestashop.core.admin.lang.repository' - '@doctrine.orm.default_entity_manager' \ No newline at end of file diff --git a/controllers/front/CommentGrade.php b/controllers/front/CommentGrade.php index e9cb4940..23e0381c 100644 --- a/controllers/front/CommentGrade.php +++ b/controllers/front/CommentGrade.php @@ -30,20 +30,28 @@ class ProductCommentsCommentGradeModuleFrontController extends ModuleFrontContro public function display() { $idProducts = Tools::getValue('id_products'); - /* @var ProductCommentRepository $productCommentRepository */ header('Content-Type: application/json'); if (!is_array($idProducts)) { - return $this->ajaxRender(null); + $this->ajaxRender(null); + + return; } $idProducts = array_unique(array_map('intval', $idProducts)); - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); + /** @var ProductCommentRepository $commentRepository */ + $commentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); + + if (!$commentRepository instanceof ProductCommentRepository) { + $this->ajaxRender(null); + + return; + } - $productsCommentsNb = $productCommentRepository->getCommentsNumberForProducts($idProducts, Configuration::get('PRODUCT_COMMENTS_MODERATE')); - $averageGrade = $productCommentRepository->getAverageGrades($idProducts, Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $productsCommentsNb = $commentRepository->getCommentsNumberForProducts($idProducts, Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $averageGrade = $commentRepository->getAverageGrades($idProducts, Configuration::get('PRODUCT_COMMENTS_MODERATE')); $resultFormated = []; diff --git a/controllers/front/ListComments.php b/controllers/front/ListComments.php index b5c87bab..8af7f4d0 100644 --- a/controllers/front/ListComments.php +++ b/controllers/front/ListComments.php @@ -29,6 +29,8 @@ class ProductCommentsListCommentsModuleFrontController extends ModuleFrontContro { public function display() { + header('Content-Type: application/json'); + $idProduct = (int) Tools::getValue('id_product'); $page = (int) Tools::getValue('page', 1); $isLastNameAnonymous = Configuration::get('PRODUCT_COMMENTS_ANONYMISATION'); @@ -85,7 +87,6 @@ public function display() $responseArray['comments'][] = $productComment; } - header('Content-Type: application/json'); $this->ajaxRender( json_encode( $responseArray diff --git a/controllers/front/PostComment.php b/controllers/front/PostComment.php index 34d6e4be..01359b55 100644 --- a/controllers/front/PostComment.php +++ b/controllers/front/PostComment.php @@ -53,7 +53,7 @@ public function display() ) ); - return false; + return; } $id_product = (int) Tools::getValue('id_product'); @@ -79,7 +79,7 @@ public function display() ) ); - return false; + return; } /** @var EntityManagerInterface $entityManager */ @@ -110,7 +110,7 @@ public function display() ) ); - return false; + return; } $entityManager->persist($productComment); diff --git a/controllers/front/ReportComment.php b/controllers/front/ReportComment.php index 9be0af98..4634de2e 100644 --- a/controllers/front/ReportComment.php +++ b/controllers/front/ReportComment.php @@ -44,7 +44,7 @@ public function display() ) ); - return false; + return; } $id_product_comment = (int) Tools::getValue('id_product_comment'); @@ -65,7 +65,7 @@ public function display() ) ); - return false; + return; } $productCommentAbuseRepository = $entityManager->getRepository(ProductCommentReport::class); @@ -85,7 +85,7 @@ public function display() ) ); - return false; + return; } $productCommentAbuse = new ProductCommentReport( diff --git a/controllers/front/UpdateCommentUsefulness.php b/controllers/front/UpdateCommentUsefulness.php index 774435b9..6342992a 100644 --- a/controllers/front/UpdateCommentUsefulness.php +++ b/controllers/front/UpdateCommentUsefulness.php @@ -44,7 +44,7 @@ public function display() ) ); - return false; + return; } $customerId = (int) $this->context->cookie->id_customer; @@ -67,7 +67,7 @@ public function display() ) ); - return false; + return; } $id_product_comment = (int) Tools::getValue('id_product_comment'); @@ -89,7 +89,7 @@ public function display() ) ); - return false; + return; } $productCommentUsefulnesRepository = $entityManager->getRepository(ProductCommentUsefulness::class); diff --git a/productcomments.php b/productcomments.php index 851d063c..27869459 100644 --- a/productcomments.php +++ b/productcomments.php @@ -29,17 +29,24 @@ } use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterion; +use PrestaShop\Module\ProductComment\Form\ProductCommentCriterionFormDataHandler; +use PrestaShop\Module\ProductComment\Form\ProductCommentCriterionFormDataProvider; +use PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository; +use PrestaShop\Module\ProductComment\Repository\ProductCommentRepository; use PrestaShop\PrestaShop\Core\Module\WidgetInterface; class ProductComments extends Module implements WidgetInterface { const INSTALL_SQL_FILE = 'install.sql'; + /** + * @var string + */ private $_html = ''; - - private $_productCommentsCriterionTypes = []; + /** + * @var string + */ private $_baseUrl; - private $langId; private $shopId; @@ -170,8 +177,11 @@ protected function _postProcess() { $id_product_comment = (int) Tools::getValue('id_product_comment'); $id_product_comment_criterion = (int) Tools::getValue('id_product_comment_criterion'); + /** @var ProductCommentRepository $commentRepository */ $commentRepository = $this->get('product_comment_repository'); + /** @var ProductCommentCriterionRepository $criterionRepository */ $criterionRepository = $this->get('product_comment_criterion_repository'); + /** @var ProductCommentCriterionFormDataHandler $criterionFormHandler */ $criterionFormHandler = $this->get('product_comment_criterion_form_data_handler'); if (Tools::isSubmit('submitModerate')) { @@ -287,7 +297,6 @@ public function getContent() } $this->_setBaseUrl(); - $this->_productCommentsCriterionTypes = $this->get('product_comment_criterion_repository')->getTypes(); $this->context->controller->addJs($this->_path . 'js/moderate.js'); @@ -433,6 +442,7 @@ public function renderConfigForm() public function renderModerateLists() { $return = null; + /** @var ProductCommentRepository $commentRepository */ $commentRepository = $this->get('product_comment_repository'); if (Configuration::get('PRODUCT_COMMENTS_MODERATE')) { @@ -528,7 +538,9 @@ public function displayNoabuseLink($token, $id, $name = null) public function renderCriterionList() { - $criterions = $this->get('product_comment_criterion_repository')->getCriterions($this->langId, false, false); + /** @var ProductCommentCriterionRepository $criterionRepository */ + $criterionRepository = $this->get('product_comment_criterion_repository'); + $criterions = $criterionRepository->getCriterions($this->langId, false, false); $fields_list = [ 'id_product_comment_criterion' => [ @@ -592,6 +604,7 @@ public function renderCommentsList() $pagination = ($pagination = Tools::getValue($helper->list_id . '_pagination')) ? (int) $pagination : 50; $moderate = Configuration::get('PRODUCT_COMMENTS_MODERATE'); + /** @var ProductCommentRepository $commentRepository */ $commentRepository = $this->get('product_comment_repository'); if (empty($moderate)) { $comments = $commentRepository->getByValidate($this->langId, $this->shopId, 0, false, $page, $pagination, true); @@ -620,7 +633,7 @@ public function getConfigFieldsValues() public function getCriterionFieldsValues(int $id = 0) { - $criterionRepos = $this->get('product_comment_criterion_repository'); + /** @var ProductCommentCriterionFormDataProvider $criterionFormProvider */ $criterionFormProvider = $this->get('product_comment_criterion_form_data_provider'); if ($id > 0) { @@ -713,7 +726,10 @@ public function renderAuthorName($value, $row) public function renderCriterionForm($id_criterion = 0) { - $types = $this->get('product_comment_criterion_repository')->getTypes(); + /** @var ProductCommentCriterionRepository $criterionRepository */ + $criterionRepository = $this->get('product_comment_criterion_repository'); + + $types = $criterionRepository->getTypes(); $query = []; foreach ($types as $key => $value) { $query[] = [ @@ -722,8 +738,6 @@ public function renderCriterionForm($id_criterion = 0) ]; } - $criterionRepository = $this->get('product_comment_criterion_repository'); - $criterion = $criterionRepository->find($id_criterion); $selected_categories = $criterionRepository->getCategories($id_criterion); @@ -859,9 +873,9 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) if ($id_criterion == 0) { $selected_cat = []; } else { + /** @var ProductCommentCriterionRepository $criterionRepository */ $criterionRepository = $this->get('product_comment_criterion_repository'); - $criterion = $criterionRepository->find((int) $id_criterion); - $selected_cat = $criterionRepository->getCategories($criterion); + $selected_cat = $criterionRepository->getCategories((int) $id_criterion); } if (Shop::getContext() == Shop::CONTEXT_SHOP && Tools::isSubmit('id_shop')) { @@ -879,8 +893,9 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) public function hookActionDeleteGDPRCustomer($customer) { if (isset($customer['id'])) { - $productCommentRepository = $this->get('product_comment_repository'); - $productCommentRepository->cleanCustomerData($customer['id']); + /** @var ProductCommentRepository $commentRepository */ + $commentRepository = $this->get('product_comment_repository'); + $commentRepository->cleanCustomerData($customer['id']); } return true; @@ -889,10 +904,11 @@ public function hookActionDeleteGDPRCustomer($customer) public function hookActionExportGDPRData($customer) { if (isset($customer['id'])) { - $productCommentRepository = $this->get('product_comment_repository'); + /** @var ProductCommentRepository $commentRepository */ + $commentRepository = $this->get('product_comment_repository'); $langId = isset($customer['id_lang']) ? $customer['id_lang'] : $this->langId; - return json_encode($productCommentRepository->getCustomerData($customer['id'], $langId)); + return json_encode($commentRepository->getCustomerData($customer['id'], $langId)); } } @@ -946,6 +962,7 @@ public function hookFilterProductContent(array $params) if (empty($params['object']->id)) { return $params; } + /** @var ProductCommentRepository $commentRepository */ $commentRepository = $this->get('product_comment_repository'); $averageRating = $commentRepository->getAverageGrade($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); $nbComments = $commentRepository->getCommentsNumber($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); @@ -971,6 +988,7 @@ public function hookFilterProductContent(array $params) */ private function renderProductCommentsList($product) { + /** @var ProductCommentRepository $commentRepository */ $commentRepository = $this->get('product_comment_repository'); $averageGrade = $commentRepository->getAverageGrade($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); $commentsNb = $commentRepository->getCommentsNumber($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); @@ -1019,6 +1037,7 @@ private function renderProductCommentsList($product) */ private function renderProductCommentModal($product) { + /** @var ProductCommentCriterionRepository $criterionRepository */ $criterionRepository = $this->get('product_comment_criterion_repository'); $criterions = $criterionRepository->getByProduct($product->id, $this->langId); @@ -1040,6 +1059,7 @@ private function renderProductCommentModal($product) public function getWidgetVariables($hookName = null, array $configuration = []) { + /** @var ProductCommentRepository $commentRepository */ $commentRepository = $this->get('product_comment_repository'); $averageGrade = $commentRepository->getAverageGrade($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE')); $commentsNb = $commentRepository->getCommentsNumber($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE')); @@ -1057,6 +1077,9 @@ public function renderWidget($hookName = null, array $configuration = []) $variables = []; $tplHookPath = 'module:productcomments/views/templates/hook/'; + /** @var \ProductControllerCore $controller */ + $controller = $this->context->controller; + if ('displayProductListReviews' === $hookName || isset($configuration['type']) && 'product_list' === $configuration['type']) { $product = $configuration['product']; $idProduct = $product['id_product']; @@ -1068,8 +1091,8 @@ public function renderWidget($hookName = null, array $configuration = []) ]); $filePath = $tplHookPath . 'product-list-reviews.tpl'; - } elseif ($this->context->controller instanceof ProductControllerCore) { - $idProduct = $this->context->controller->getProduct()->id; + } elseif ($controller instanceof ProductControllerCore) { + $idProduct = $controller->getProduct()->id; $variables = $this->getWidgetVariables($hookName, ['id_product' => $idProduct]); switch (Tools::getValue('action')) { diff --git a/src/Entity/ProductCommentGrade.php b/src/Entity/ProductCommentGrade.php index 0aae703d..7b06e7d0 100644 --- a/src/Entity/ProductCommentGrade.php +++ b/src/Entity/ProductCommentGrade.php @@ -71,7 +71,7 @@ public function __construct( } /** - * @return mixed + * @return ProductComment */ public function getComment() { @@ -79,10 +79,15 @@ public function getComment() } /** - * @return mixed + * @return ProductCommentCriterion */ public function getCriterion() { return $this->criterion; } + + public function getGrade(): int + { + return $this->grade; + } } diff --git a/src/Form/ProductCommentCriterionFormDataHandler.php b/src/Form/ProductCommentCriterionFormDataHandler.php index 8e0437d9..2f15e7c3 100644 --- a/src/Form/ProductCommentCriterionFormDataHandler.php +++ b/src/Form/ProductCommentCriterionFormDataHandler.php @@ -24,17 +24,11 @@ use Doctrine\ORM\EntityManagerInterface; use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterion; use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterionLang; -use PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository; use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataHandler\FormDataHandlerInterface; use PrestaShopBundle\Entity\Repository\LangRepository; class ProductCommentCriterionFormDataHandler implements FormDataHandlerInterface { - /** - * @var ProductCommentCriterionRepository - */ - private $pccriterionRepository; - /** * @var LangRepository */ @@ -46,16 +40,13 @@ class ProductCommentCriterionFormDataHandler implements FormDataHandlerInterface private $entityManager; /** - * @param ProductCommentCriterionRepository $pccriterionRepository * @param LangRepository $langRepository * @param EntityManagerInterface $entityManager */ public function __construct( - ProductCommentCriterionRepository $pccriterionRepository, LangRepository $langRepository, EntityManagerInterface $entityManager ) { - $this->pccriterionRepository = $pccriterionRepository; $this->langRepository = $langRepository; $this->entityManager = $entityManager; } diff --git a/src/Repository/ProductCommentCriterionRepository.php b/src/Repository/ProductCommentCriterionRepository.php index 6b142af2..d634dc01 100644 --- a/src/Repository/ProductCommentCriterionRepository.php +++ b/src/Repository/ProductCommentCriterionRepository.php @@ -43,11 +43,6 @@ */ class ProductCommentCriterionRepository extends ServiceEntityRepository { - /** - * @var ManagerRegistry the Doctrine Registry - */ - private $registry; - /** * @var Connection the Database connection */ diff --git a/src/Repository/ProductCommentRepository.php b/src/Repository/ProductCommentRepository.php index 88db9688..0292723a 100644 --- a/src/Repository/ProductCommentRepository.php +++ b/src/Repository/ProductCommentRepository.php @@ -43,11 +43,6 @@ */ class ProductCommentRepository extends ServiceEntityRepository { - /** - * @var ManagerRegistry the Doctrine Registry - */ - private $registry; - /** * @var Connection the Database connection */ diff --git a/tests/phpstan/index.php b/tests/php/index.php similarity index 100% rename from tests/phpstan/index.php rename to tests/php/index.php diff --git a/tests/php/phpstan/index.php b/tests/php/phpstan/index.php new file mode 100644 index 00000000..45df26c5 --- /dev/null +++ b/tests/php/phpstan/index.php @@ -0,0 +1,34 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) + */ +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); + +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + +header('Location: ../'); +exit; diff --git a/tests/php/phpstan/phpstan-8.2.x.neon b/tests/php/phpstan/phpstan-8.2.x.neon new file mode 100644 index 00000000..b048e5fd --- /dev/null +++ b/tests/php/phpstan/phpstan-8.2.x.neon @@ -0,0 +1,18 @@ +includes: + - %currentWorkingDirectory%/tests/php/phpstan/phpstan.neon + +parameters: + ignoreErrors: + - '#Method ProductCommentsCommentGradeModuleFrontController::display\(\) should return bool but empty return statement found.#' + - '#Method ProductCommentsPostCommentModuleFrontController::display\(\) should return bool but empty return statement found.#' + - '#Method ProductCommentsReportCommentModuleFrontController::display\(\) should return bool but empty return statement found.#' + - '#Method ProductCommentsUpdateCommentUsefulnessModuleFrontController::display\(\) should return bool but empty return statement found.#' + - '#Method ProductCommentsCommentGradeModuleFrontController::display\(\) should return bool but return statement is missing.#' + - '#Method ProductCommentsListCommentsModuleFrontController::display\(\) should return bool but return statement is missing.#' + - '#Method ProductCommentsPostCommentModuleFrontController::display\(\) should return bool but return statement is missing.#' + - '#Method ProductCommentsReportCommentModuleFrontController::display\(\) should return bool but return statement is missing.#' + - '#Method ProductCommentsUpdateCommentUsefulnessModuleFrontController::display\(\) should return bool but return statement is missing.#' + - '#Property [a-zA-Z0-9\\_]+::\$id is never written, only read.#' + - '#Call to an undefined method AdminController\|FrontController\|PrestaShopBundle\\Bridge\\AdminController\\LegacyControllerBridgeInterface::getProduct\(\).#' + - '#Cannot call method getAverageGrade\(\) on object\|false.#' + - '#Cannot call method getCommentsNumber\(\) on object\|false.#' \ No newline at end of file diff --git a/tests/php/phpstan/phpstan-9.0.3.neon b/tests/php/phpstan/phpstan-9.0.3.neon new file mode 100644 index 00000000..dcce4f57 --- /dev/null +++ b/tests/php/phpstan/phpstan-9.0.3.neon @@ -0,0 +1,6 @@ +includes: + - %currentWorkingDirectory%/tests/php/phpstan/phpstan.neon + +parameters: + ignoreErrors: + - '#Call to an undefined method AdminController\|FrontController\|PrestaShop\\PrestaShop\\Core\\Context\\LegacyControllerContext::getProduct\(\).#' \ No newline at end of file diff --git a/tests/php/phpstan/phpstan-9.1.x.neon b/tests/php/phpstan/phpstan-9.1.x.neon new file mode 100644 index 00000000..dcce4f57 --- /dev/null +++ b/tests/php/phpstan/phpstan-9.1.x.neon @@ -0,0 +1,6 @@ +includes: + - %currentWorkingDirectory%/tests/php/phpstan/phpstan.neon + +parameters: + ignoreErrors: + - '#Call to an undefined method AdminController\|FrontController\|PrestaShop\\PrestaShop\\Core\\Context\\LegacyControllerContext::getProduct\(\).#' \ No newline at end of file diff --git a/tests/php/phpstan/phpstan-develop.neon b/tests/php/phpstan/phpstan-develop.neon new file mode 100644 index 00000000..dcce4f57 --- /dev/null +++ b/tests/php/phpstan/phpstan-develop.neon @@ -0,0 +1,6 @@ +includes: + - %currentWorkingDirectory%/tests/php/phpstan/phpstan.neon + +parameters: + ignoreErrors: + - '#Call to an undefined method AdminController\|FrontController\|PrestaShop\\PrestaShop\\Core\\Context\\LegacyControllerContext::getProduct\(\).#' \ No newline at end of file diff --git a/tests/php/phpstan/phpstan.neon b/tests/php/phpstan/phpstan.neon new file mode 100644 index 00000000..018ab98c --- /dev/null +++ b/tests/php/phpstan/phpstan.neon @@ -0,0 +1,2 @@ + # Base PHPStan configuration for the module + # This file is included by version-specific configs \ No newline at end of file diff --git a/tests/php/phpstan/prepend-constants.php b/tests/php/phpstan/prepend-constants.php new file mode 100644 index 00000000..733689a6 --- /dev/null +++ b/tests/php/phpstan/prepend-constants.php @@ -0,0 +1,11 @@ + but class [a-zA-Z0-9\\_]+ is not generic.#' - path: ../../src/Repository diff --git a/tests/phpstan/phpstan-1.7.8.neon b/tests/phpstan/phpstan-1.7.8.neon deleted file mode 100644 index e6ad951a..00000000 --- a/tests/phpstan/phpstan-1.7.8.neon +++ /dev/null @@ -1,12 +0,0 @@ -includes: - - %currentWorkingDirectory%/tests/phpstan/phpstan.neon - -parameters: - ignoreErrors: - - '#Access to an undefined property Cookie::\$id_customer.#' - - '#Access to an undefined property Cookie::\$id_guest.#' - - '#Access to an undefined property HelperList::\$list_id.#' - - '#Access to an undefined property HelperList::\$shopLinkType.#' - - - message: '#PHPDoc tag @extends contains generic type [a-zA-Z0-9\\_]+<[a-zA-Z0-9\\_]+> but class [a-zA-Z0-9\\_]+ is not generic.#' - path: ../../src/Repository diff --git a/tests/phpstan/phpstan-8.0.neon b/tests/phpstan/phpstan-8.0.neon deleted file mode 100644 index 23b71e8d..00000000 --- a/tests/phpstan/phpstan-8.0.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - %currentWorkingDirectory%/tests/phpstan/phpstan.neon - -parameters: - ignoreErrors: diff --git a/tests/phpstan/phpstan-latest.neon b/tests/phpstan/phpstan-latest.neon deleted file mode 100644 index c604f7c7..00000000 --- a/tests/phpstan/phpstan-latest.neon +++ /dev/null @@ -1,2 +0,0 @@ -includes: - - %currentWorkingDirectory%/tests/phpstan/phpstan.neon diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon deleted file mode 100644 index 0961334b..00000000 --- a/tests/phpstan/phpstan.neon +++ /dev/null @@ -1,16 +0,0 @@ -includes: - - %currentWorkingDirectory%/vendor/prestashop/php-dev-tools/phpstan/ps-module-extension.neon -parameters: - paths: - # From PHPStan 0.12, paths to check are relative to the neon file - - ../../productcomments.php - - ../../ProductComment.php - - ../../ProductCommentCriterion.php - - ../../controllers/ - - ../../src/ - - ../../upgrade/ - level: 5 - ignoreErrors: - - - message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#' - path: ../../productcomments.php From 07cbf1e2bda53f279ed86623878c23244c92cdac Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 15 Jul 2026 16:31:51 +0200 Subject: [PATCH 06/23] CI : PHPCSFixer with common action --- .github/workflows/php.yml | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 1175e62b..7b1ceb58 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -32,26 +32,11 @@ jobs: name: PHP-CS-Fixer runs-on: ubuntu-latest steps: - - name: Setup PHP - uses: shivammathur/setup-php@v2 + - name: Run PHP-CS-Fixer + uses: PrestaShop/.github/.github/actions/php-ci/php-cs@master with: php-version: '7.4' - - name: Checkout - uses: actions/checkout@v4 - - - name: Cache dependencies - uses: actions/cache@v4 - with: - path: vendor - key: php-${{ hashFiles('composer.lock') }} - - - name: Install dependencies - run: composer install - - - name: Run PHP-CS-Fixer - run: ./vendor/bin/php-cs-fixer fix --dry-run --diff --using-cache=no - # Run PHPStan against the module (PHP 7.4 – PS 8.2) phpstan-74-81: name: PHPStan (PHP 7.4 - 8.1) From f9965f87a2dd1b35aae660575caf8f5a4eaf4ad6 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 17 Jul 2026 09:51:19 +0200 Subject: [PATCH 07/23] PHP support from 7.2 to 8.5 (PS 8.2+) --- .github/workflows/php.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 7b1ceb58..7e50c37c 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -1,13 +1,12 @@ name: PHP tests on: [push, pull_request] jobs: - # Check there is no syntax errors in the project php-linter: - name: PHP Syntax check 7.2 => 8.2 + name: PHP Syntax check 7.2 => 8.5 runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: PHP syntax checker 7.2 uses: prestashop/github-action-php-lint/7.2@master @@ -25,7 +24,16 @@ jobs: uses: prestashop/github-action-php-lint/8.1@master - name: PHP syntax checker 8.2 - uses: prestashop/github-action-php-lint/8.2@master + uses: prestashop/github-action-php-lint/8.2@master + + - name: PHP syntax checker 8.3 + uses: prestashop/github-action-php-lint/8.3@master + + - name: PHP syntax checker 8.4 + uses: prestashop/github-action-php-lint/8.4@master + + - name: PHP syntax checker 8.5 + uses: prestashop/github-action-php-lint/8.5@master # Check the PHP code follow the coding standards php-cs-fixer: @@ -35,7 +43,7 @@ jobs: - name: Run PHP-CS-Fixer uses: PrestaShop/.github/.github/actions/php-ci/php-cs@master with: - php-version: '7.4' + php-version: '7.4' # Run PHPStan against the module (PHP 7.4 – PS 8.2) phpstan-74-81: From a49ab798a83928829f0dd54a89ac98080432eaf5 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Mon, 20 Jul 2026 09:45:04 +0200 Subject: [PATCH 08/23] Support for PS 8.2+ (& Cleanup code) --- README.md | 2 +- productcomments.php | 2 +- .../admin/_configure/helpers/form/form.tpl | 22 +------------------ 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 0f18c6d9..43de567b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Allow users to post reviews on your products and/or rate them based on specific ## Compatibility -PrestaShop: `1.7.8` or newer +PrestaShop: `8.2.0` or newer ## Multistore compatibility diff --git a/productcomments.php b/productcomments.php index c81d290e..ef3eb093 100644 --- a/productcomments.php +++ b/productcomments.php @@ -79,7 +79,7 @@ public function __construct() $this->langId = $this->context->language->id; $this->shopId = $this->context->shop->id ? $this->context->shop->id : Configuration::get('PS_SHOP_DEFAULT'); - $this->ps_versions_compliancy = ['min' => '1.7.8', 'max' => _PS_VERSION_]; + $this->ps_versions_compliancy = ['min' => '8.2.0', 'max' => _PS_VERSION_]; } public function install($keep = true) diff --git a/views/templates/admin/_configure/helpers/form/form.tpl b/views/templates/admin/_configure/helpers/form/form.tpl index 4b7ebdec..6e1e1375 100644 --- a/views/templates/admin/_configure/helpers/form/form.tpl +++ b/views/templates/admin/_configure/helpers/form/form.tpl @@ -44,27 +44,7 @@ {/foreach} - {elseif $input.type == 'switch' && $smarty.const._PS_VERSION_|@addcslashes:'\'' < '1.6'} - {foreach $input.values as $value} - - - {if isset($input.br) && $input.br}
{/if} - {if isset($value.p) && $value.p}

{$value.p}

{/if} - {/foreach} {else} {$smarty.block.parent} - {/if} - + {/if} {/block} From b45093d86208064a5ab7b6bb6f6001be35e98c33 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Tue, 21 Jul 2026 09:39:51 +0200 Subject: [PATCH 09/23] Support for PrestaShop 9.2.x --- .github/workflows/php.yml | 2 +- tests/php/phpstan/phpstan-9.2.x.neon | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 tests/php/phpstan/phpstan-9.2.x.neon diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 7e50c37c..c3f1508a 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -121,7 +121,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - presta_version: ['9.1.x', 'develop'] + presta_version: ['9.1.x', '9.2.x', 'develop'] php_version: ['8.1', '8.5'] fail-fast: false env: diff --git a/tests/php/phpstan/phpstan-9.2.x.neon b/tests/php/phpstan/phpstan-9.2.x.neon new file mode 100644 index 00000000..dcce4f57 --- /dev/null +++ b/tests/php/phpstan/phpstan-9.2.x.neon @@ -0,0 +1,6 @@ +includes: + - %currentWorkingDirectory%/tests/php/phpstan/phpstan.neon + +parameters: + ignoreErrors: + - '#Call to an undefined method AdminController\|FrontController\|PrestaShop\\PrestaShop\\Core\\Context\\LegacyControllerContext::getProduct\(\).#' \ No newline at end of file From 83e86072a137356d1b4bd2554be778ceb66b9912 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Thu, 23 Jul 2026 11:17:42 +0200 Subject: [PATCH 10/23] CI : Dependabot (PHP / Node / Github Actions) --- .github/dependabot.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e1818d46..f85296b6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,16 +1,23 @@ version: 2 updates: -- package-ecosystem: npm +- package-ecosystem: composer directory: "/" schedule: interval: daily time: "04:00" open-pull-requests-limit: 10 target-branch: dev -- package-ecosystem: composer +- package-ecosystem: github-actions directory: "/" schedule: interval: daily time: "04:00" open-pull-requests-limit: 10 target-branch: dev +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily + time: "04:00" + open-pull-requests-limit: 10 + target-branch: dev \ No newline at end of file From ed7b1ee93d223d37f3589005dcf7809fda99fd09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 12:08:14 +0000 Subject: [PATCH 11/23] Bump actions/upload-artifact from 4 to 7 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 32dfb883..4dc7c122 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -17,7 +17,7 @@ jobs: - name: Generate index.php run: ~/.composer/vendor/bin/autoindex - name: Create & upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ github.event.repository.name }} path: /home/runner/work/${{ github.event.repository.name }} From d55cab495bdfba900d1583177dab629c7a38357e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 08:27:58 +0000 Subject: [PATCH 12/23] Bump toolmantim/release-drafter from 5 to 7 Bumps [toolmantim/release-drafter](https://github.com/toolmantim/release-drafter) from 5 to 7. - [Release notes](https://github.com/toolmantim/release-drafter/releases) - [Commits](https://github.com/toolmantim/release-drafter/compare/v5...v7) --- updated-dependencies: - dependency-name: toolmantim/release-drafter dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 4dc7c122..50789991 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -32,7 +32,7 @@ jobs: name: ${{ github.event.repository.name }} path: ${{ github.event.repository.name }} - id: release_info - uses: toolmantim/release-drafter@v5 + uses: toolmantim/release-drafter@v7 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Prepare for Release From e20ddcdd1483f24b064d59788fda150c835b08f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 09:07:50 +0000 Subject: [PATCH 13/23] Bump actions/checkout from 4 to 7 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release.yml | 2 +- .github/workflows/php.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 50789991..a48039b7 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Install composer dependencies run: composer install --no-dev -o - name: Clean-up project diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index c3f1508a..302ffb46 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -58,7 +58,7 @@ jobs: PHPRC: ${{ github.workspace }}/${{ github.event.repository.name }}/.phpstan-php-ini steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: path: ${{ github.event.repository.name }} @@ -94,7 +94,7 @@ jobs: PHPRC: ${{ github.workspace }}/${{ github.event.repository.name }}/.phpstan-php-ini steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: path: ${{ github.event.repository.name }} @@ -128,7 +128,7 @@ jobs: PHPRC: ${{ github.workspace }}/${{ github.event.repository.name }}/.phpstan-php-ini steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: path: ${{ github.event.repository.name }} From 73208435bdee6680adb5c1c639774076dc43b3ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:05:54 +0000 Subject: [PATCH 14/23] Bump actions/download-artifact from 4 to 8 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 8. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v8) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index a48039b7..3f16d7b4 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -27,7 +27,7 @@ jobs: if: github.event_name == 'push' && (github.event.ref == 'refs/heads/main' || github.event.ref == 'refs/heads/master') steps: - name: Download artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: ${{ github.event.repository.name }} path: ${{ github.event.repository.name }} From 97c9caf5f18d6a0c83cba4398ea84710443acbd4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 13:42:55 +0000 Subject: [PATCH 15/23] Bump PrestaShopCorp/github-action-clean-before-deploy from 1.0 to 2.0 Bumps [PrestaShopCorp/github-action-clean-before-deploy](https://github.com/prestashopcorp/github-action-clean-before-deploy) from 1.0 to 2.0. - [Release notes](https://github.com/prestashopcorp/github-action-clean-before-deploy/releases) - [Commits](https://github.com/prestashopcorp/github-action-clean-before-deploy/compare/v1.0...v2.0) --- updated-dependencies: - dependency-name: PrestaShopCorp/github-action-clean-before-deploy dependency-version: '2.0' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 3f16d7b4..3af78041 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -11,7 +11,7 @@ jobs: - name: Install composer dependencies run: composer install --no-dev -o - name: Clean-up project - uses: PrestaShopCorp/github-action-clean-before-deploy@v1.0 + uses: PrestaShopCorp/github-action-clean-before-deploy@v2.0 - name: Prepare auto-index tool run: composer global require prestashop/autoindex - name: Generate index.php From ce44d0425defcd385ef00d5f0b867a0270c1be69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 04:14:39 +0000 Subject: [PATCH 16/23] Bump toolmantim/release-drafter from 7 to 7.6.0 Bumps [toolmantim/release-drafter](https://github.com/toolmantim/release-drafter) from 7 to 7.6.0. - [Release notes](https://github.com/toolmantim/release-drafter/releases) - [Commits](https://github.com/toolmantim/release-drafter/compare/v7...v7.6.0) --- updated-dependencies: - dependency-name: toolmantim/release-drafter dependency-version: 7.6.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 3af78041..abef8c3d 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -32,7 +32,7 @@ jobs: name: ${{ github.event.repository.name }} path: ${{ github.event.repository.name }} - id: release_info - uses: toolmantim/release-drafter@v7 + uses: toolmantim/release-drafter@v7.6.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Prepare for Release From 469e234a44bee5bea66dfa88962097bf5e5922f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 05:33:02 +0000 Subject: [PATCH 17/23] Bump toolmantim/release-drafter from 7.6.0 to 7.7.0 Bumps [toolmantim/release-drafter](https://github.com/toolmantim/release-drafter) from 7.6.0 to 7.7.0. - [Release notes](https://github.com/toolmantim/release-drafter/releases) - [Commits](https://github.com/toolmantim/release-drafter/compare/v7.6.0...v7.7.0) --- updated-dependencies: - dependency-name: toolmantim/release-drafter dependency-version: 7.7.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index abef8c3d..172ce9c6 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -32,7 +32,7 @@ jobs: name: ${{ github.event.repository.name }} path: ${{ github.event.repository.name }} - id: release_info - uses: toolmantim/release-drafter@v7.6.0 + uses: toolmantim/release-drafter@v7.7.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Prepare for Release From 62df4506ae62cdc573692fabba320d02b1fc0d3a Mon Sep 17 00:00:00 2001 From: Jonathan LELIEVRE Date: Thu, 6 Aug 2026 14:29:18 +0200 Subject: [PATCH 18/23] Replace 9.1.x branch with 9.1.4 tag in CI --- .github/workflows/php.yml | 2 +- tests/php/phpstan/{phpstan-9.1.x.neon => phpstan-9.1.4.neon} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/php/phpstan/{phpstan-9.1.x.neon => phpstan-9.1.4.neon} (100%) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 302ffb46..8d93c3b3 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -121,7 +121,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - presta_version: ['9.1.x', '9.2.x', 'develop'] + presta_version: ['9.1.4', '9.2.x', 'develop'] php_version: ['8.1', '8.5'] fail-fast: false env: diff --git a/tests/php/phpstan/phpstan-9.1.x.neon b/tests/php/phpstan/phpstan-9.1.4.neon similarity index 100% rename from tests/php/phpstan/phpstan-9.1.x.neon rename to tests/php/phpstan/phpstan-9.1.4.neon From 548c4ecb1a13d1f0a72e6e2e79faf029613c5662 Mon Sep 17 00:00:00 2001 From: mattgoud Date: Fri, 28 Aug 2026 15:07:59 +0200 Subject: [PATCH 19/23] CI: pin PrestaShop 9.1.5 instead of the superseded 9.1.4 tag 9.1.5 is the last release of the 9.1 line: the 9.1.x branch was deleted from the core once it shipped, so nothing newer will come out of it. --- .github/workflows/php.yml | 2 +- tests/php/phpstan/{phpstan-9.1.4.neon => phpstan-9.1.5.neon} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/php/phpstan/{phpstan-9.1.4.neon => phpstan-9.1.5.neon} (100%) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 8d93c3b3..c4cb6c4a 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -121,7 +121,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - presta_version: ['9.1.4', '9.2.x', 'develop'] + presta_version: ['9.1.5', '9.2.x', 'develop'] php_version: ['8.1', '8.5'] fail-fast: false env: diff --git a/tests/php/phpstan/phpstan-9.1.4.neon b/tests/php/phpstan/phpstan-9.1.5.neon similarity index 100% rename from tests/php/phpstan/phpstan-9.1.4.neon rename to tests/php/phpstan/phpstan-9.1.5.neon From 512a88f84b2158cef99f91f5910938e3792a2da4 Mon Sep 17 00:00:00 2001 From: Thomas N Date: Wed, 9 Sep 2026 09:43:53 +0100 Subject: [PATCH 20/23] Bump to v9.0.0 --- config.xml | 2 +- productcomments.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.xml b/config.xml index b1f5984a..ba407583 100644 --- a/config.xml +++ b/config.xml @@ -2,7 +2,7 @@ productcomments - + diff --git a/productcomments.php b/productcomments.php index ef3eb093..f272ec1f 100644 --- a/productcomments.php +++ b/productcomments.php @@ -66,7 +66,7 @@ public function __construct() { $this->name = 'productcomments'; $this->tab = 'front_office_features'; - $this->version = '8.0.1'; + $this->version = '9.0.0'; $this->author = 'PrestaShop'; $this->need_instance = 0; $this->bootstrap = true; From f2e23c0319afa06a78bc691e38a5f4b862599ba2 Mon Sep 17 00:00:00 2001 From: Thomas N Date: Wed, 9 Sep 2026 09:51:48 +0100 Subject: [PATCH 21/23] Rename upgrade file --- upgrade/{install-8.0.1.php => install-9.0.0.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename upgrade/{install-8.0.1.php => install-9.0.0.php} (96%) diff --git a/upgrade/install-8.0.1.php b/upgrade/install-9.0.0.php similarity index 96% rename from upgrade/install-8.0.1.php rename to upgrade/install-9.0.0.php index 29d2e1bb..dc970fa3 100644 --- a/upgrade/install-8.0.1.php +++ b/upgrade/install-9.0.0.php @@ -27,7 +27,7 @@ exit; } -function upgrade_module_8_0_1($object) +function upgrade_module_9_0_0($object) { return $object->registerHook('actionFrontControllerSetVariables'); } From 1df82bea4d08cbb74f49cc8d4a20163800eefaf7 Mon Sep 17 00:00:00 2001 From: Thomas N Date: Wed, 9 Sep 2026 10:14:27 +0100 Subject: [PATCH 22/23] Fix PHPStan error --- controllers/front/CommentGrade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/front/CommentGrade.php b/controllers/front/CommentGrade.php index 23e0381c..51560ca3 100644 --- a/controllers/front/CommentGrade.php +++ b/controllers/front/CommentGrade.php @@ -41,7 +41,7 @@ public function display() $idProducts = array_unique(array_map('intval', $idProducts)); - /** @var ProductCommentRepository $commentRepository */ + /** @var ProductCommentRepository|null $commentRepository */ $commentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); if (!$commentRepository instanceof ProductCommentRepository) { From 8458c23c1d6a5ee2f5232e4c67ef0ccdb070989f Mon Sep 17 00:00:00 2001 From: Thomas N Date: Wed, 9 Sep 2026 10:20:23 +0100 Subject: [PATCH 23/23] Remove ignored statement --- productcomments.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/productcomments.php b/productcomments.php index ef3eb093..02c7149b 100644 --- a/productcomments.php +++ b/productcomments.php @@ -33,6 +33,7 @@ use PrestaShop\Module\ProductComment\Form\ProductCommentCriterionFormDataProvider; use PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository; use PrestaShop\Module\ProductComment\Repository\ProductCommentRepository; +use PrestaShop\PrestaShop\Adapter\Presenter\Product\ProductLazyArray; use PrestaShop\PrestaShop\Core\Module\WidgetInterface; class ProductComments extends Module implements WidgetInterface @@ -929,7 +930,7 @@ public function hookDisplayFooterProduct($params) /** * Inject data about productcomments in the product object for frontoffice. This is the older way of adding the data before PrestaShop 9.2. * - * @param array $params + * @param array{object: ProductLazyArray} $params * * @return array */ @@ -943,7 +944,10 @@ public function hookFilterProductContent(array $params) $averageRating = $commentRepository->getAverageGrade($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); $nbComments = $commentRepository->getCommentsNumber($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); - /* @phpstan-ignore-next-line */ + /* + * @phpstan-ignore-next-line + * Needs #[AllowDynamicProperties] on ProductLazyArray class to avoid error in PHP 8.2+ + */ $params['object']->productComments = [ 'averageRating' => $averageRating, 'nbComments' => $nbComments,