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
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 }}
diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml
index 32dfb883..172ce9c6 100644
--- a/.github/workflows/build-release.yml
+++ b/.github/workflows/build-release.yml
@@ -7,17 +7,17 @@ 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
- 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
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 }}
@@ -27,12 +27,12 @@ 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 }}
- id: release_info
- uses: toolmantim/release-drafter@v5
+ uses: toolmantim/release-drafter@v7.7.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare for Release
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index 8e08b03f..c4cb6c4a 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,65 +24,127 @@ 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:
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
+ php-version: '7.4'
- - name: Cache dependencies
- uses: actions/cache@v4
+ # 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_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: Checkout repository
+ uses: actions/checkout@v7
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 and a PrestaShop release
- phpstan:
- name: PHPStan
+ 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:
+ 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-versions: ['1.7.8', '8.0', 'latest']
+ 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: Setup PHP
- uses: shivammathur/setup-php@v2
+ - name: Checkout repository
+ uses: actions/checkout@v7
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 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:
- path: vendor
- key: php-${{ hashFiles('composer.lock') }}
+ 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
- # Add composer local folder in cache to make next builds faster
- - name: Cache composer folder
- uses: actions/cache@v4
+ # 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.5', '9.2.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@v7
with:
- path: ~/.composer/cache
- key: php-composer-cache
-
- - run: composer install
-
- # 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 }}
+ 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/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/config.xml b/config.xml
index 958f4458..ba407583 100644
--- a/config.xml
+++ b/config.xml
@@ -2,11 +2,11 @@
productcomments
-
+
1
0
-
+
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..51560ca3 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|null $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..875f40d7 100644
--- a/productcomments.php
+++ b/productcomments.php
@@ -29,25 +29,45 @@
}
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\Adapter\Presenter\Product\ProductLazyArray;
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;
+ 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 = '9.0.0';
$this->author = 'PrestaShop';
$this->need_instance = 0;
$this->bootstrap = true;
@@ -60,7 +80,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)
@@ -85,66 +105,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()
@@ -170,8 +154,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 +274,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 +419,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 +515,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 +581,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 +610,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 +703,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 +715,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 +850,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 +870,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 +881,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));
}
}
@@ -935,9 +928,9 @@ 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
+ * @param array{object: ProductLazyArray} $params
*
* @return array
*/
@@ -946,11 +939,15 @@ 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'));
- /* @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,
@@ -971,6 +968,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 +1017,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 +1039,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 +1057,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 +1071,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')) {
@@ -1112,4 +1115,41 @@ 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'));
+
+ // 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,
+ '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/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..46295a5c 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
*/
@@ -159,12 +154,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 +170,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]
);
}
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.5.neon b/tests/php/phpstan/phpstan-9.1.5.neon
new file mode 100644
index 00000000..dcce4f57
--- /dev/null
+++ b/tests/php/phpstan/phpstan-9.1.5.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.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
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
diff --git a/upgrade/install-9.0.0.php b/upgrade/install-9.0.0.php
new file mode 100644
index 00000000..dc970fa3
--- /dev/null
+++ b/upgrade/install-9.0.0.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_9_0_0($object)
+{
+ return $object->registerHook('actionFrontControllerSetVariables');
+}
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}