From d8353d1374b07eabace32bde937ebeb3877f08e8 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Thu, 13 Jul 2023 20:04:03 +0700 Subject: [PATCH 01/27] add EntityManager for repositories --- config/common.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/common.yml b/config/common.yml index b57877fa..67af6a71 100644 --- a/config/common.yml +++ b/config/common.yml @@ -5,12 +5,14 @@ services: product_comment_criterion_repository: class: PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository arguments: + - '@doctrine' - '@doctrine.dbal.default_connection' - '%database_prefix%' product_comment_repository: class: PrestaShop\Module\ProductComment\Repository\ProductCommentRepository arguments: + - '@doctrine' - '@doctrine.dbal.default_connection' - '%database_prefix%' - '@=service("prestashop.adapter.legacy.configuration").get("PRODUCT_COMMENTS_ALLOW_GUESTS")' From 9ef98760cb90e905cbe2f16b75d4ed51466bcd8e Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Thu, 13 Jul 2023 20:09:00 +0700 Subject: [PATCH 02/27] extends ServiceEntityRepository, migrate functions from OM to doctrine --- .../ProductCommentCriterionRepository.php | 70 +++++- src/Repository/ProductCommentRepository.php | 216 +++++++++++++++++- 2 files changed, 282 insertions(+), 4 deletions(-) diff --git a/src/Repository/ProductCommentCriterionRepository.php b/src/Repository/ProductCommentCriterionRepository.php index 41f5fa5c..0c88b35f 100644 --- a/src/Repository/ProductCommentCriterionRepository.php +++ b/src/Repository/ProductCommentCriterionRepository.php @@ -26,12 +26,26 @@ namespace PrestaShop\Module\ProductComment\Repository; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterion; -class ProductCommentCriterionRepository +/** + * @extends ServiceEntityRepository + * + * @method ProductCommentCriterion|null find($id, $lockMode = null, $lockVersion = null) + * @method ProductCommentCriterion|null findOneBy(array $criteria, array $orderBy = null) + * @method ProductCommentCriterion[] findAll() + * @method ProductCommentCriterion[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ProductCommentCriterionRepository extends ServiceEntityRepository { + /** + * @var ManagerRegistry the EntityManager + */ + private $registry; + /** * @var Connection the Database connection */ @@ -43,11 +57,13 @@ class ProductCommentCriterionRepository private $databasePrefix; /** + * @param ManagerRegistry $registry * @param Connection $connection * @param string $databasePrefix */ - public function __construct(Connection $connection, $databasePrefix) + public function __construct($registry, $connection, $databasePrefix) { + parent::__construct($registry, ProductCommentCriterion::class); $this->connection = $connection; $this->databasePrefix = $databasePrefix; } @@ -88,4 +104,54 @@ public function getByProduct($idProduct, $idLang) return $qb->execute()->fetchAll(); } + + /** + * @param ProductCommentCriterion $entity + * + * @return array + * + */ + public function getProducts($entity) + { + $sql = ' + SELECT pccp.id_product, pccp.id_product_comment_criterion + FROM `' . _DB_PREFIX_ . 'product_comment_criterion_product` pccp + WHERE pccp.id_product_comment_criterion = ' . $entity->getId(); + + $res = $this->connection->executeQuery($sql)->fetchAll(); + + $products = []; + if ($res) { + foreach ($res as $row) { + $products[] = (int) $row['id_product']; + } + } + + return $products; + } + + /** + * @param ProductCommentCriterion $entity + * + * @return array + * + */ + public function getCategories(ProductCommentCriterion $entity) + { + $sql = ' + SELECT pccc.id_category, pccc.id_product_comment_criterion + FROM `' . _DB_PREFIX_ . 'product_comment_criterion_category` pccc + WHERE pccc.id_product_comment_criterion = ' . $entity->getId(); + + $res = $this->connection->executeQuery($sql)->fetchAll(); + + $criterions = []; + if ($res) { + foreach ($res as $row) { + $criterions[] = (int) $row['id_category']; + } + } + + return $criterions; + } } diff --git a/src/Repository/ProductCommentRepository.php b/src/Repository/ProductCommentRepository.php index a1e0d1a3..1bc3c553 100644 --- a/src/Repository/ProductCommentRepository.php +++ b/src/Repository/ProductCommentRepository.php @@ -26,11 +26,34 @@ namespace PrestaShop\Module\ProductComment\Repository; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; +use Hook; +use PrestaShop\Module\ProductComment\Entity\ProductComment; -class ProductCommentRepository +/* +use Doctrine\DBAL\Cache\QueryCacheProfile; +use Doctrine\Common\Cache\Psr6\DoctrineProvider; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; +*/ + +/** + * @extends ServiceEntityRepository + * + * @method ProductComment|null find($id, $lockMode = null, $lockVersion = null) + * @method ProductComment|null findOneBy(array $criteria, array $orderBy = null) + * @method ProductComment[] findAll() + * @method ProductComment[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ProductCommentRepository extends ServiceEntityRepository { + /** + * @var ManagerRegistry the EntityManager + */ + private $registry; + /** * @var Connection the Database connection */ @@ -54,21 +77,53 @@ class ProductCommentRepository const DEFAULT_COMMENTS_PER_PAGE = 5; /** + * @param ManagerRegistry $registry * @param Connection $connection * @param string $databasePrefix * @param bool $guestCommentsAllowed * @param int $commentsMinimalTime */ public function __construct( - Connection $connection, + $registry, + $connection, $databasePrefix, $guestCommentsAllowed, $commentsMinimalTime ) { + parent::__construct($registry, ProductComment::class); $this->connection = $connection; $this->databasePrefix = $databasePrefix; $this->guestCommentsAllowed = (bool) $guestCommentsAllowed; $this->commentsMinimalTime = (int) $commentsMinimalTime; + /* Only works since PS 8.0.0 - Doctrine\Cache 1.11.x + $cachePool = new FilesystemAdapter(); + $cache = DoctrineProvider::wrap($cachePool); + $config = $this->connection->getConfiguration(); + $config->setResultCacheImpl($cache); + */ + } + + public function add(ProductComment $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(ProductComment $entity, bool $flush = false): void + { + $entityId = $entity->getId(); + + $this->getEntityManager()->remove($entity); + if ($flush) { + $this->getEntityManager()->flush(); + } + + $this->deleteGrades($entityId); + $this->deleteReports($entityId); + $this->deleteUsefulness($entityId); } /** @@ -171,6 +226,85 @@ public function getAverageGrade($productId, $validatedOnly) return (float) $qb->execute()->fetchColumn(); } + /** + * @param int $langId + * @param int $shopId + * @param int $validate + * @param bool $deleted + * @param int $p + * @param int $limit + * @param bool $skip_validate + * + * @return array + */ + public function getByValidate($langId, $shopId, $validate = 0, $deleted = false, $p = null, $limit = null, $skip_validate = false) + { + /** @var QueryBuilder $qb */ + $qb = $this->connection->createQueryBuilder(); + $qb + ->select('pc.`id_product_comment`, pc.`id_product`, c.id_customer AS customer_id, + IF(c.id_customer, CONCAT(c.`firstname`, \' \', c.`lastname`), pc.customer_name) customer_name, + pc.`title`, pc.`content`, pc.`grade`, pc.`date_add`, pl.`name`') + ->from($this->databasePrefix . 'product_comment', 'pc') + ->leftJoin('pc', $this->databasePrefix . 'customer', 'c', 'pc.id_customer = c.id_customer') + ->leftJoin('pc', $this->databasePrefix . 'product_lang', 'pl', 'pc.id_product = pl.id_product') + ->andWhere('pc.deleted = :deleted') + ->setParameter('deleted', $deleted) + ->andWhere('pl.id_lang = :id_lang') + ->setParameter('id_lang', $langId) + ->andWhere('pl.id_shop = :id_shop') + ->setParameter('id_shop', $shopId) + ->addOrderBy('pc.date_add', 'DESC') + ; + + if (!$skip_validate) { + $qb + ->andWhere('pc.validate = :validate') + ->setParameter('validate', $validate) + ; + } + if ($p && $limit) { + $limit = (int) $limit; + $offset = ($p - 1) * $limit; + $qb + ->setFirstResult($offset) + ->setMaxResults($limit); + } + + return $this->connection->executeQuery( + $qb->getSQL(), $qb->getParameters(), $qb->getParameterTypes() + //, new QueryCacheProfile(300, "product-comments-getByValidate") + )->fetchAll(); + } + + /** + * @param int $validate + * @param bool $skip_validate + * + * @return int + */ + public function getCountByValidate($validate = 0, $skip_validate = false) + { + /** @var QueryBuilder $qb */ + $qb = $this->connection->createQueryBuilder(); + $qb + ->select('COUNT(*)') + ->from($this->databasePrefix . 'product_comment', 'pc') + ; + + if (!$skip_validate) { + $qb + ->andWhere('pc.validate = :validate') + ->setParameter('validate', $validate) + ; + } + + return (int) $this->connection->executeQuery( + $qb->getSQL(), $qb->getParameters(), $qb->getParameterTypes() + //, new QueryCacheProfile(300, "product-comments-getCountByValidate") + )->fetchColumn(); + } + /** * @param array $productIds * @param bool $validatedOnly @@ -416,4 +550,82 @@ private function getLastComment(array $criteria) return empty($comments) ? [] : $comments[0]; } + + /** + * @param string $validate + * @param ProductComment $productComment + * + * @return bool + */ + public function validate($validate = '1', $productComment) + { + $success = ($this->connection->executeQuery(' + UPDATE `' . _DB_PREFIX_ . 'product_comment` SET + `validate` = ' . (int) $validate . ' + WHERE `id_product_comment` = ' . $productComment->getId())); + + Hook::exec('actionObjectProductCommentValidateAfter', ['object' => $productComment]); + + return $success; + } + + /** + * @param int $id_product_comment + * + * @return bool + */ + public function deleteGrades($id_product_comment) + { + return $this->connection->executeQuery(' + DELETE FROM `' . _DB_PREFIX_ . 'product_comment_grade` + WHERE `id_product_comment` = ' . $id_product_comment); + } + + /** + * @param int $id_product_comment + * + * @return bool + */ + public function deleteReports($id_product_comment) + { + return $this->connection->executeQuery(' + DELETE FROM `' . $this->databasePrefix . 'product_comment_report` + WHERE `id_product_comment` = ' . $id_product_comment); + } + + /** + * @param int $id_product_comment + * + * @return bool + */ + public function deleteUsefulness($id_product_comment) + { + return $this->connection->executeQuery(' + DELETE FROM `' . _DB_PREFIX_ . 'product_comment_usefulness` + WHERE `id_product_comment` = ' . $id_product_comment); + } + + /** + * @param int $langId + * @param int $shopId + * + * @return array + */ + public function getReportedComments($langId, $shopId) + { + $sql = 'SELECT DISTINCT(pc.`id_product_comment`), pc.`id_product`, pc.`content`, pc.`grade`, pc.`date_add`, pc.`title` + , IF(c.id_customer, CONCAT(c.`firstname`, \' \', c.`lastname`), pc.customer_name) customer_name, pl.`name` + FROM `' . $this->databasePrefix . 'product_comment_report` pcr + LEFT JOIN `' . $this->databasePrefix . 'product_comment` pc + ON pcr.id_product_comment = pc.id_product_comment + LEFT JOIN `' . $this->databasePrefix . 'customer` c ON (c.`id_customer` = pc.`id_customer`) + LEFT JOIN `' . $this->databasePrefix . 'product_lang` pl ON ' . + '(pl.`id_product` = pc.`id_product` ' . + ' AND pl.`id_lang` = ' . $langId . + ' AND pl.`id_shop` = ' . $shopId . + ') + ORDER BY pc.`date_add` DESC'; + + return $this->connection->executeQuery($sql)->fetchAll(); + } } From ee934e7ce3d73e455d40561406c1efda05dfa09c Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Thu, 13 Jul 2023 20:10:44 +0700 Subject: [PATCH 03/27] mark migrated functions as Deprecated --- ProductComment.php | 19 +++++++++++++++++++ ProductCommentCriterion.php | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/ProductComment.php b/ProductComment.php index 9d5cd015..f3fc56a6 100644 --- a/ProductComment.php +++ b/ProductComment.php @@ -190,6 +190,9 @@ public static function getRatings($id_product) return Db::getInstance((bool) _PS_USE_SQL_SLAVE_)->getRow($sql); } + /** + * @deprecated 4.0.0 + */ public static function getAverageGrade($id_product) { $validate = Configuration::get('PRODUCT_COMMENTS_MODERATE'); @@ -235,6 +238,8 @@ public static function getAveragesByProduct($id_product, $id_lang) * Return number of comments and average grade by products * * @return int|false + * + * @deprecated 4.0.0 */ public static function getCommentNumber($id_product) { @@ -279,6 +284,8 @@ public static function getGradedCommentNumber($id_product) * Get comments by Validation * * @return array Comments + * + * @deprecated 6.0.0 */ public static function getByValidate($validate = '0', $deleted = false, $p = null, $limit = null, $skip_validate = false) { @@ -306,6 +313,8 @@ public static function getByValidate($validate = '0', $deleted = false, $p = nul * Get numbers of comments by Validation * * @return int Count of comments + * + * @deprecated 6.0.0 */ public static function getCountByValidate($validate = '0', $skip_validate = false) { @@ -360,6 +369,8 @@ public function validate($validate = '1') * Delete a comment, grade and report data * * @return bool succeed + * + * @deprecated 6.0.0 */ public function delete() { @@ -373,6 +384,8 @@ public function delete() * Delete Grades * * @return bool succeed + * + * @deprecated 6.0.0 */ public static function deleteGrades($id_product_comment) { @@ -389,6 +402,8 @@ public static function deleteGrades($id_product_comment) * Delete Reports * * @return bool succeed + * + * @deprecated 6.0.0 */ public static function deleteReports($id_product_comment) { @@ -405,6 +420,8 @@ public static function deleteReports($id_product_comment) * Delete usefulness * * @return bool succeed + * + * @deprecated 6.0.0 */ public static function deleteUsefulness($id_product_comment) { @@ -473,6 +490,8 @@ public static function isAlreadyUsefulness($id_product_comment, $id_customer) * Get reported comments * * @return array Comments + * + * @deprecated 6.0.0 */ public static function getReportedComments() { diff --git a/ProductCommentCriterion.php b/ProductCommentCriterion.php index e1c0e538..067a0fc9 100644 --- a/ProductCommentCriterion.php +++ b/ProductCommentCriterion.php @@ -154,6 +154,8 @@ public function addGrade($id_product_comment, $grade) * Get criterion by Product * * @return array Criterion + * + * @deprecated 4.0.0 */ public static function getByProduct($id_product, $id_lang) { @@ -240,6 +242,9 @@ public function getProducts() return $products; } + /** + * @deprecated 6.0.0 + */ public function getCategories() { $res = Db::getInstance()->executeS(' From 8b07a78ff5cd907b032a2b2da36578d5f75f300a Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Thu, 13 Jul 2023 20:25:37 +0700 Subject: [PATCH 04/27] replace OM functions by equivalent doctrine ones --- productcomments.php | 88 +++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/productcomments.php b/productcomments.php index 99a505b7..3cf64dde 100644 --- a/productcomments.php +++ b/productcomments.php @@ -41,11 +41,14 @@ class ProductComments extends Module implements WidgetInterface private $_productCommentsCriterionTypes = []; private $_baseUrl; + private $langId; + private $shopId; + public function __construct() { $this->name = 'productcomments'; $this->tab = 'front_office_features'; - $this->version = '5.0.3'; + $this->version = '6.0.0'; $this->author = 'PrestaShop'; $this->need_instance = 0; $this->bootstrap = true; @@ -55,7 +58,10 @@ public function __construct() $this->displayName = $this->trans('Product Comments', [], 'Modules.Productcomments.Admin'); $this->description = $this->trans('Allow users to post reviews on your products and/or rate them based on specific criteria.', [], 'Modules.Productcomments.Admin'); - $this->ps_versions_compliancy = ['min' => '1.7.6', 'max' => _PS_VERSION_]; + $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.7', 'max' => _PS_VERSION_]; } public function install($keep = true) @@ -194,13 +200,13 @@ protected function _postProcess() } } elseif (Tools::isSubmit('productcomments')) { $id_product_comment = (int) Tools::getValue('id_product_comment'); - $comment = new ProductComment($id_product_comment); - $comment->validate(); - ProductComment::deleteReports($id_product_comment); + $comment = $this->get('product_comment_repository') . find($id_product_comment); + $this->get('product_comment_repository')->validate('1', $comment); + $this->get('product_comment_repository')->deleteReports($id_product_comment); } elseif (Tools::isSubmit('deleteproductcomments')) { $id_product_comment = (int) Tools::getValue('id_product_comment'); - $comment = new ProductComment($id_product_comment); - $comment->delete(); + $comment = $this->get('product_comment_repository')->find($id_product_comment); + $this->get('product_comment_repository')->remove($comment, true); } elseif (Tools::isSubmit('submitEditCriterion')) { $criterion = new ProductCommentCriterion((int) Tools::getValue('id_product_comment_criterion')); $criterion->id_product_comment_criterion_type = (int) Tools::getValue('id_product_comment_criterion_type'); @@ -259,10 +265,10 @@ protected function _postProcess() } Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name, 'tab_module' => $this->tab, 'conf' => 4, 'module_name' => $this->name])); } elseif ($id_product_comment = (int) Tools::getValue('approveComment')) { - $comment = new ProductComment($id_product_comment); - $comment->validate(); + $comment = $this->get('product_comment_repository')->find($id_product_comment); + $this->get('product_comment_repository')->validate('1', $comment); } elseif ($id_product_comment = (int) Tools::getValue('noabuseComment')) { - ProductComment::deleteReports($id_product_comment); + $this->get('product_comment_repository')->deleteReports($id_product_comment); Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name])); } @@ -271,7 +277,6 @@ protected function _postProcess() public function getContent() { - include_once dirname(__FILE__) . '/ProductComment.php'; include_once dirname(__FILE__) . '/ProductCommentCriterion.php'; $this->_html = ''; @@ -423,7 +428,7 @@ public function renderConfigForm() $helper->tpl_vars = [ 'fields_value' => $this->getConfigFieldsValues(), 'languages' => $this->context->controller->getLanguages(), - 'id_language' => $this->context->language->id, + 'id_language' => $this->langId, ]; return $helper->generateForm([$fields_form_1]); @@ -434,7 +439,7 @@ public function renderModerateLists() $return = null; if (Configuration::get('PRODUCT_COMMENTS_MODERATE')) { - $comments = ProductComment::getByValidate(0, false); + $comments = $this->get('product_comment_repository')->getByValidate($this->langId, $this->shopId, 0, false); $fields_list = $this->getStandardFieldList(); @@ -459,7 +464,7 @@ public function renderModerateLists() $return .= $helper->generateList($comments, $fields_list); } - $comments = ProductComment::getReportedComments(); + $comments = $this->get('product_comment_repository')->getReportedComments($this->langId, $this->shopId); $fields_list = $this->getStandardFieldList(); @@ -526,7 +531,7 @@ public function displayNoabuseLink($token, $id, $name = null) public function renderCriterionList() { - $criterions = ProductCommentCriterion::getCriterions($this->context->language->id, false, false); + $criterions = ProductCommentCriterion::getCriterions($this->langId, false, false); $fields_list = [ 'id_product_comment_criterion' => [ @@ -591,11 +596,11 @@ public function renderCommentsList() $moderate = Configuration::get('PRODUCT_COMMENTS_MODERATE'); if (empty($moderate)) { - $comments = ProductComment::getByValidate(0, false, (int) $page, (int) $pagination, true); - $count = (int) ProductComment::getCountByValidate(0, true); + $comments = $this->get('product_comment_repository')->getByValidate($this->langId, $this->shopId, 0, false, (int) $page, (int) $pagination, true); + $count = $this->get('product_comment_repository')->getCountByValidate(0, true); } else { - $comments = ProductComment::getByValidate(1, false, (int) $page, (int) $pagination); - $count = (int) ProductComment::getCountByValidate(1); + $comments = $this->get('product_comment_repository')->getByValidate($this->langId, $this->shopId, 1, false, (int) $page, (int) $pagination); + $count = $this->get('product_comment_repository')->getCountByValidate(1); } $helper->listTotal = $count; @@ -712,11 +717,12 @@ public function renderCriterionForm($id_criterion = 0) ]; } - $criterion = new ProductCommentCriterion((int) $id_criterion); - $selected_categories = $criterion->getCategories(); + $criterionRepository = $this->get('product_comment_criterion_repository'); + $criterion = $criterionRepository->find((int) $id_criterion); + $selected_categories = $criterionRepository->getCategories($criterion); - $product_table_values = Product::getSimpleProducts($this->context->language->id); - $selected_products = $criterion->getProducts(); + $product_table_values = Product::getSimpleProducts($this->langId); + $selected_products = $criterionRepository->getProducts($criterion); foreach ($product_table_values as $key => $product) { if (false !== array_search($product['id_product'], $selected_products)) { $product_table_values[$key]['selected'] = 1; @@ -830,7 +836,7 @@ public function renderCriterionForm($id_criterion = 0) $helper->tpl_vars = [ 'fields_value' => $this->getCriterionFieldsValues($id_criterion), 'languages' => $this->context->controller->getLanguages(), - 'id_language' => $this->context->language->id, + 'id_language' => $this->langId, ]; return $helper->generateForm([$fields_form_1]); @@ -846,8 +852,11 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) if ($id_criterion == 0) { $selected_cat = []; } else { + /* $pdc_object = new ProductCommentCriterion($id_criterion); $selected_cat = $pdc_object->getCategories(); + */ + } if (Shop::getContext() == Shop::CONTEXT_SHOP && Tools::isSubmit('id_shop')) { @@ -855,7 +864,7 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) } else { $root_category = new Category($id_root); } - $root_category = ['id_category' => $root_category->id, 'name' => $root_category->name[$this->context->language->id]]; + $root_category = ['id_category' => $root_category->id, 'name' => $root_category->name[$this->langId]]; $helper = new Helper(); @@ -864,9 +873,8 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) public function hookActionDeleteGDPRCustomer($customer) { - if (isset($customer['id'])) { - /** @var ProductCommentRepository $productCommentRepository */ - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); + if (isset($customer['id'])) { + $productCommentRepository = $this->get('product_comment_repository'); $productCommentRepository->cleanCustomerData($customer['id']); } @@ -875,10 +883,9 @@ public function hookActionDeleteGDPRCustomer($customer) public function hookActionExportGDPRData($customer) { - if (isset($customer['id'])) { - /** @var ProductCommentRepository $productCommentRepository */ - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); - $langId = isset($customer['id_lang']) ? $customer['id_lang'] : $this->context->language->id; + if (isset($customer['id'])) { + $productCommentRepository = $this->get('product_comment_repository'); + $langId = isset($customer['id_lang']) ? $customer['id_lang'] : $this->langId; return json_encode($productCommentRepository->getCustomerData($customer['id'], $langId)); } @@ -934,9 +941,7 @@ public function hookFilterProductContent(array $params) if (empty($params['object']->id)) { return $params; } - /** @var ProductCommentRepository $productCommentRepository */ - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); - + $productCommentRepository = $this->get('product_comment_repository'); $averageRating = $productCommentRepository->getAverageGrade($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); $nbComments = $productCommentRepository->getCommentsNumber($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); @@ -961,9 +966,7 @@ public function hookFilterProductContent(array $params) */ private function renderProductCommentsList($product) { - /** @var ProductCommentRepository $productCommentRepository */ - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); - + $productCommentRepository = $this->get('product_comment_repository'); $averageGrade = $productCommentRepository->getAverageGrade($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); $commentsNb = $productCommentRepository->getCommentsNumber($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); $isPostAllowed = $productCommentRepository->isPostAllowed($product->id, (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest); @@ -1010,10 +1013,9 @@ private function renderProductCommentsList($product) * @throws SmartyException */ private function renderProductCommentModal($product) - { - /** @var ProductCommentCriterionRepository $criterionRepository */ - $criterionRepository = $this->context->controller->getContainer()->get('product_comment_criterion_repository'); - $criterions = $criterionRepository->getByProduct($product->id, $this->context->language->id); + { + $criterionRepository = $this->get('product_comment_criterion_repository'); + $criterions = $criterionRepository->getByProduct($product->id, $this->langId); $this->context->smarty->assign([ 'logged' => (bool) $this->context->cookie->id_customer, @@ -1033,7 +1035,7 @@ private function renderProductCommentModal($product) public function getWidgetVariables($hookName = null, array $configuration = []) { - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); + $productCommentRepository = $this->get('product_comment_repository'); $averageGrade = $productCommentRepository->getAverageGrade($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE')); $commentsNb = $productCommentRepository->getCommentsNumber($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE')); $isPostAllowed = $productCommentRepository->isPostAllowed($configuration['id_product'], (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest); From a16013f591a1fbca66fcbbf297d2edc5f4b31a9b Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Thu, 13 Jul 2023 20:36:39 +0700 Subject: [PATCH 05/27] php-cs fix --- ProductCommentCriterion.php | 2 +- productcomments.php | 11 ++++------- src/Repository/ProductCommentCriterionRepository.php | 6 ++---- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/ProductCommentCriterion.php b/ProductCommentCriterion.php index 067a0fc9..cd29cf76 100644 --- a/ProductCommentCriterion.php +++ b/ProductCommentCriterion.php @@ -154,7 +154,7 @@ public function addGrade($id_product_comment, $grade) * Get criterion by Product * * @return array Criterion - * + * * @deprecated 4.0.0 */ public static function getByProduct($id_product, $id_lang) diff --git a/productcomments.php b/productcomments.php index 3cf64dde..d1ba3e9c 100644 --- a/productcomments.php +++ b/productcomments.php @@ -28,8 +28,6 @@ exit; } -use PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository; -use PrestaShop\Module\ProductComment\Repository\ProductCommentRepository; use PrestaShop\PrestaShop\Core\Module\WidgetInterface; class ProductComments extends Module implements WidgetInterface @@ -717,7 +715,7 @@ public function renderCriterionForm($id_criterion = 0) ]; } - $criterionRepository = $this->get('product_comment_criterion_repository'); + $criterionRepository = $this->get('product_comment_criterion_repository'); $criterion = $criterionRepository->find((int) $id_criterion); $selected_categories = $criterionRepository->getCategories($criterion); @@ -856,7 +854,6 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) $pdc_object = new ProductCommentCriterion($id_criterion); $selected_cat = $pdc_object->getCategories(); */ - } if (Shop::getContext() == Shop::CONTEXT_SHOP && Tools::isSubmit('id_shop')) { @@ -873,7 +870,7 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) public function hookActionDeleteGDPRCustomer($customer) { - if (isset($customer['id'])) { + if (isset($customer['id'])) { $productCommentRepository = $this->get('product_comment_repository'); $productCommentRepository->cleanCustomerData($customer['id']); } @@ -883,7 +880,7 @@ public function hookActionDeleteGDPRCustomer($customer) public function hookActionExportGDPRData($customer) { - if (isset($customer['id'])) { + if (isset($customer['id'])) { $productCommentRepository = $this->get('product_comment_repository'); $langId = isset($customer['id_lang']) ? $customer['id_lang'] : $this->langId; @@ -1013,7 +1010,7 @@ private function renderProductCommentsList($product) * @throws SmartyException */ private function renderProductCommentModal($product) - { + { $criterionRepository = $this->get('product_comment_criterion_repository'); $criterions = $criterionRepository->getByProduct($product->id, $this->langId); diff --git a/src/Repository/ProductCommentCriterionRepository.php b/src/Repository/ProductCommentCriterionRepository.php index 0c88b35f..ab25f98e 100644 --- a/src/Repository/ProductCommentCriterionRepository.php +++ b/src/Repository/ProductCommentCriterionRepository.php @@ -107,9 +107,8 @@ public function getByProduct($idProduct, $idLang) /** * @param ProductCommentCriterion $entity - * + * * @return array - * */ public function getProducts($entity) { @@ -132,9 +131,8 @@ public function getProducts($entity) /** * @param ProductCommentCriterion $entity - * + * * @return array - * */ public function getCategories(ProductCommentCriterion $entity) { From 15440da3a81c443389f93379fcccce8cb98ae6c1 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Fri, 14 Jul 2023 13:52:51 +0700 Subject: [PATCH 06/27] phpstan and phpcsfixer fixes --- .../ProductCommentCriterionRepository.php | 5 +++-- src/Repository/ProductCommentRepository.php | 22 ++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/Repository/ProductCommentCriterionRepository.php b/src/Repository/ProductCommentCriterionRepository.php index ab25f98e..7eeb7f5c 100644 --- a/src/Repository/ProductCommentCriterionRepository.php +++ b/src/Repository/ProductCommentCriterionRepository.php @@ -29,6 +29,7 @@ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterion; /** @@ -36,8 +37,8 @@ * * @method ProductCommentCriterion|null find($id, $lockMode = null, $lockVersion = null) * @method ProductCommentCriterion|null findOneBy(array $criteria, array $orderBy = null) - * @method ProductCommentCriterion[] findAll() - * @method ProductCommentCriterion[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + * @method ProductCommentCriterion[] findAll() + * @method ProductCommentCriterion[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class ProductCommentCriterionRepository extends ServiceEntityRepository { diff --git a/src/Repository/ProductCommentRepository.php b/src/Repository/ProductCommentRepository.php index 1bc3c553..c30f3f60 100644 --- a/src/Repository/ProductCommentRepository.php +++ b/src/Repository/ProductCommentRepository.php @@ -44,8 +44,8 @@ * * @method ProductComment|null find($id, $lockMode = null, $lockVersion = null) * @method ProductComment|null findOneBy(array $criteria, array $orderBy = null) - * @method ProductComment[] findAll() - * @method ProductComment[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + * @method ProductComment[] findAll() + * @method ProductComment[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class ProductCommentRepository extends ServiceEntityRepository { @@ -559,14 +559,14 @@ private function getLastComment(array $criteria) */ public function validate($validate = '1', $productComment) { - $success = ($this->connection->executeQuery(' + $success = $this->connection->executeStatement(' UPDATE `' . _DB_PREFIX_ . 'product_comment` SET `validate` = ' . (int) $validate . ' - WHERE `id_product_comment` = ' . $productComment->getId())); + WHERE `id_product_comment` = ' . $productComment->getId()); Hook::exec('actionObjectProductCommentValidateAfter', ['object' => $productComment]); - return $success; + return (bool) $success; } /** @@ -576,9 +576,11 @@ public function validate($validate = '1', $productComment) */ public function deleteGrades($id_product_comment) { - return $this->connection->executeQuery(' + $success = $this->connection->executeStatement(' DELETE FROM `' . _DB_PREFIX_ . 'product_comment_grade` WHERE `id_product_comment` = ' . $id_product_comment); + + return (bool) $success; } /** @@ -588,9 +590,11 @@ public function deleteGrades($id_product_comment) */ public function deleteReports($id_product_comment) { - return $this->connection->executeQuery(' + $success = $this->connection->executeStatement(' DELETE FROM `' . $this->databasePrefix . 'product_comment_report` WHERE `id_product_comment` = ' . $id_product_comment); + + return (bool) $success; } /** @@ -600,9 +604,11 @@ public function deleteReports($id_product_comment) */ public function deleteUsefulness($id_product_comment) { - return $this->connection->executeQuery(' + $success = $this->connection->executeStatement(' DELETE FROM `' . _DB_PREFIX_ . 'product_comment_usefulness` WHERE `id_product_comment` = ' . $id_product_comment); + + return (bool) $success; } /** From 683a40a993fa9fcfeb8f5dcdd26e8f9c90dac6f0 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Fri, 14 Jul 2023 14:36:11 +0700 Subject: [PATCH 07/27] restore needed use --- productcomments.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/productcomments.php b/productcomments.php index d1ba3e9c..810b6da0 100644 --- a/productcomments.php +++ b/productcomments.php @@ -28,6 +28,8 @@ exit; } +use PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository; +use PrestaShop\Module\ProductComment\Repository\ProductCommentRepository; use PrestaShop\PrestaShop\Core\Module\WidgetInterface; class ProductComments extends Module implements WidgetInterface From 19f5d78a151e07e53e74534d0ba3269ac76b0355 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Fri, 14 Jul 2023 14:39:44 +0700 Subject: [PATCH 08/27] php-cs-fixer remove indirect use --- productcomments.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/productcomments.php b/productcomments.php index 810b6da0..d1ba3e9c 100644 --- a/productcomments.php +++ b/productcomments.php @@ -28,8 +28,6 @@ exit; } -use PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository; -use PrestaShop\Module\ProductComment\Repository\ProductCommentRepository; use PrestaShop\PrestaShop\Core\Module\WidgetInterface; class ProductComments extends Module implements WidgetInterface From 7a4d1721efc64d6f063c1b9a5bcbcb9507070969 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Fri, 14 Jul 2023 14:54:08 +0700 Subject: [PATCH 09/27] backwards compatibility with DBAL 2.9 --- src/Repository/ProductCommentRepository.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Repository/ProductCommentRepository.php b/src/Repository/ProductCommentRepository.php index c30f3f60..4ec08baf 100644 --- a/src/Repository/ProductCommentRepository.php +++ b/src/Repository/ProductCommentRepository.php @@ -559,7 +559,7 @@ private function getLastComment(array $criteria) */ public function validate($validate = '1', $productComment) { - $success = $this->connection->executeStatement(' + $success = $this->connection->executeUpdate(' UPDATE `' . _DB_PREFIX_ . 'product_comment` SET `validate` = ' . (int) $validate . ' WHERE `id_product_comment` = ' . $productComment->getId()); @@ -576,7 +576,7 @@ public function validate($validate = '1', $productComment) */ public function deleteGrades($id_product_comment) { - $success = $this->connection->executeStatement(' + $success = $this->connection->executeUpdate(' DELETE FROM `' . _DB_PREFIX_ . 'product_comment_grade` WHERE `id_product_comment` = ' . $id_product_comment); @@ -590,7 +590,7 @@ public function deleteGrades($id_product_comment) */ public function deleteReports($id_product_comment) { - $success = $this->connection->executeStatement(' + $success = $this->connection->executeUpdate(' DELETE FROM `' . $this->databasePrefix . 'product_comment_report` WHERE `id_product_comment` = ' . $id_product_comment); @@ -604,7 +604,7 @@ public function deleteReports($id_product_comment) */ public function deleteUsefulness($id_product_comment) { - $success = $this->connection->executeStatement(' + $success = $this->connection->executeUpdate(' DELETE FROM `' . _DB_PREFIX_ . 'product_comment_usefulness` WHERE `id_product_comment` = ' . $id_product_comment); From 5f52306d49841d56d856ca3bd0c3f30457b4e283 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Fri, 14 Jul 2023 22:28:52 +0700 Subject: [PATCH 10/27] migrate functions from OM to Doctrine --- .../ProductCommentCriterionRepository.php | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/Repository/ProductCommentCriterionRepository.php b/src/Repository/ProductCommentCriterionRepository.php index 7eeb7f5c..c5a3bdf5 100644 --- a/src/Repository/ProductCommentCriterionRepository.php +++ b/src/Repository/ProductCommentCriterionRepository.php @@ -31,6 +31,7 @@ use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterion; +use PrestaShop\PrestaShop\Adapter\SymfonyContainer; /** * @extends ServiceEntityRepository @@ -106,6 +107,29 @@ public function getByProduct($idProduct, $idLang) return $qb->execute()->fetchAll(); } + /** + * Get Criterions + * + * @return array Criterions + */ + public function getCriterions($id_lang, $type = false, $active = false) + { + $sql = ' + SELECT pcc.`id_product_comment_criterion`, pcc.id_product_comment_criterion_type, pccl.`name`, pcc.active + FROM `' . _DB_PREFIX_ . 'product_comment_criterion` pcc + JOIN `' . _DB_PREFIX_ . 'product_comment_criterion_lang` pccl ON (pcc.id_product_comment_criterion = pccl.id_product_comment_criterion) + WHERE pccl.`id_lang` = ' . $id_lang . ($active ? ' AND active = 1' : '') . ($type ? ' AND id_product_comment_criterion_type = ' . (int) $type : '') . ' + ORDER BY pccl.`name` ASC'; + $criterions = $this->connection->executeQuery($sql)->fetchAll(); + + $types = self::getTypes(); + foreach ($criterions as $key => $data) { + $criterions[$key]['type_name'] = $types[$data['id_product_comment_criterion_type']]; + } + + return $criterions; + } + /** * @param ProductCommentCriterion $entity * @@ -153,4 +177,18 @@ public function getCategories(ProductCommentCriterion $entity) return $criterions; } + + /** + * @return array + */ + public function getTypes() + { + $sfTranslator = SymfonyContainer::getInstance()->get('translator'); + + return [ + 1 => $sfTranslator->trans('Valid for the entire catalog', [], 'Modules.Productcomments.Admin'), + 2 => $sfTranslator->trans('Restricted to some categories', [], 'Modules.Productcomments.Admin'), + 3 => $sfTranslator->trans('Restricted to some products', [], 'Modules.Productcomments.Admin'), + ]; + } } From 564d575e57eec2d74369141c2f34adc48d7c25a7 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Fri, 14 Jul 2023 22:29:32 +0700 Subject: [PATCH 11/27] mark migrated functions as Deprecated --- ProductCommentCriterion.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ProductCommentCriterion.php b/ProductCommentCriterion.php index cd29cf76..88d5379d 100644 --- a/ProductCommentCriterion.php +++ b/ProductCommentCriterion.php @@ -203,6 +203,8 @@ public static function getByProduct($id_product, $id_lang) * Get Criterions * * @return array Criterions + * + * @deprecated 6.0.0 */ public static function getCriterions($id_lang, $type = false, $active = false) { @@ -226,6 +228,9 @@ public static function getCriterions($id_lang, $type = false, $active = false) return $criterions; } + /** + * @deprecated 6.0.0 + */ public function getProducts() { $res = Db::getInstance()->executeS(' @@ -275,6 +280,9 @@ public function deleteProducts() WHERE `id_product_comment_criterion` = ' . (int) $this->id); } + /** + * @deprecated 6.0.0 + */ public static function getTypes() { // Instance of module class for translations From 5d38a29ceaad26f0329c2ccc74a32d78de5dce94 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Fri, 14 Jul 2023 22:30:39 +0700 Subject: [PATCH 12/27] replace OM functions by Doctrine ones --- productcomments.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/productcomments.php b/productcomments.php index d1ba3e9c..6ec5b669 100644 --- a/productcomments.php +++ b/productcomments.php @@ -198,7 +198,7 @@ protected function _postProcess() } } elseif (Tools::isSubmit('productcomments')) { $id_product_comment = (int) Tools::getValue('id_product_comment'); - $comment = $this->get('product_comment_repository') . find($id_product_comment); + $comment = $this->get('product_comment_repository')->find($id_product_comment); $this->get('product_comment_repository')->validate('1', $comment); $this->get('product_comment_repository')->deleteReports($id_product_comment); } elseif (Tools::isSubmit('deleteproductcomments')) { @@ -289,7 +289,7 @@ public function getContent() } $this->_setBaseUrl(); - $this->_productCommentsCriterionTypes = ProductCommentCriterion::getTypes(); + $this->_productCommentsCriterionTypes = $this->get('product_comment_criterion_repository')->getTypes(); $this->context->controller->addJs($this->_path . 'js/moderate.js'); @@ -529,7 +529,7 @@ public function displayNoabuseLink($token, $id, $name = null) public function renderCriterionList() { - $criterions = ProductCommentCriterion::getCriterions($this->langId, false, false); + $criterions = $this->get('product_comment_criterion_repository')->getCriterions($this->langId, false, false); $fields_list = [ 'id_product_comment_criterion' => [ @@ -706,7 +706,7 @@ public function renderAuthorName($value, $row) public function renderCriterionForm($id_criterion = 0) { - $types = ProductCommentCriterion::getTypes(); + $types = $this->get('product_comment_criterion_repository')->getTypes(); $query = []; foreach ($types as $key => $value) { $query[] = [ @@ -850,10 +850,9 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) if ($id_criterion == 0) { $selected_cat = []; } else { - /* - $pdc_object = new ProductCommentCriterion($id_criterion); - $selected_cat = $pdc_object->getCategories(); - */ + $criterionRepository = $this->get('product_comment_criterion_repository'); + $criterion = $criterionRepository->find((int) $id_criterion); + $selected_cat = $criterionRepository->getCategories($criterion); } if (Shop::getContext() == Shop::CONTEXT_SHOP && Tools::isSubmit('id_shop')) { From bc546d507a2a816f425c966f52c5cd39e2de937d Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Fri, 14 Jul 2023 22:31:35 +0700 Subject: [PATCH 13/27] add new ignoreErrors --- tests/phpstan/phpstan.neon | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon index 037652f7..b6d98be7 100644 --- a/tests/phpstan/phpstan.neon +++ b/tests/phpstan/phpstan.neon @@ -9,4 +9,8 @@ parameters: - ../../controllers/ - ../../src/ - ../../upgrade/ + ignoreErrors: + - + message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#' + path: ../../productcomments.php level: 5 From ec9a3e1011d721435352a7423a90c549128c249b Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Sat, 15 Jul 2023 06:58:55 +0700 Subject: [PATCH 14/27] use newer phpstan --- tests/phpstan.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpstan.sh b/tests/phpstan.sh index 9fcc0c62..ae55264f 100755 --- a/tests/phpstan.sh +++ b/tests/phpstan.sh @@ -23,6 +23,6 @@ echo "Run PHPStan using phpstan-${PS_VERSION}.neon file" docker run --rm --volumes-from temp-ps \ -v $PWD:/var/www/html/modules/productcomments \ -e _PS_ROOT_DIR_=/var/www/html \ - --workdir=/var/www/html/modules/productcomments phpstan/phpstan:0.12 \ + --workdir=/var/www/html/modules/productcomments phpstan/phpstan:1.0 \ analyse \ --configuration=/var/www/html/modules/productcomments/tests/phpstan/phpstan-$PS_VERSION.neon From 658d63e543291a05828d8def139d798f02e44d07 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Sat, 15 Jul 2023 07:03:08 +0700 Subject: [PATCH 15/27] use latest phpstan --- tests/phpstan.sh | 2 +- tests/phpstan/phpstan-1.7.6.neon | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/phpstan.sh b/tests/phpstan.sh index ae55264f..e20e09a7 100755 --- a/tests/phpstan.sh +++ b/tests/phpstan.sh @@ -23,6 +23,6 @@ echo "Run PHPStan using phpstan-${PS_VERSION}.neon file" docker run --rm --volumes-from temp-ps \ -v $PWD:/var/www/html/modules/productcomments \ -e _PS_ROOT_DIR_=/var/www/html \ - --workdir=/var/www/html/modules/productcomments phpstan/phpstan:1.0 \ + --workdir=/var/www/html/modules/productcomments phpstan/phpstan:latest \ analyse \ --configuration=/var/www/html/modules/productcomments/tests/phpstan/phpstan-$PS_VERSION.neon diff --git a/tests/phpstan/phpstan-1.7.6.neon b/tests/phpstan/phpstan-1.7.6.neon index 8c1ccec5..914f475f 100644 --- a/tests/phpstan/phpstan-1.7.6.neon +++ b/tests/phpstan/phpstan-1.7.6.neon @@ -1,5 +1,5 @@ includes: - - %currentWorkingDirectory%/tests/phpstan/phpstan.neon + - %currentWorkingDirectory%/tests/phpstan/phpstan.neon parameters: ignoreErrors: @@ -10,3 +10,6 @@ parameters: - '#Parameter \#1 \$idCategory of class Category constructor expects null, int given.#' - '#Parameter \#1 \$value of method ControllerCore::ajaxRender\(\) expects null, string\|false given.#' - '#Parameter \#2 \$value of static method CacheCore::store\(\) expects string, array\|mysqli_result\|PDOStatement\|resource\|false\|null given.#' + - + message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#' + path: ../../productcomments.php \ No newline at end of file From 8e4a900fe756e5f8b24b200749be72cd9a940845 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Sat, 15 Jul 2023 07:14:26 +0700 Subject: [PATCH 16/27] drop PHP5.6 and PS 1.7.6 check --- .github/workflows/php.yml | 10 +++++----- tests/phpstan/phpstan-1.7.6.neon | 15 --------------- tests/phpstan/phpstan-8.0.neon | 8 ++++++++ 3 files changed, 13 insertions(+), 20 deletions(-) delete mode 100644 tests/phpstan/phpstan-1.7.6.neon create mode 100644 tests/phpstan/phpstan-8.0.neon diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 8d085483..c2c5e881 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -3,15 +3,12 @@ on: [push, pull_request] jobs: # Check there is no syntax errors in the project php-linter: - name: PHP Syntax check 5.6 => 8.1 + name: PHP Syntax check 7.2 => 8.1 runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3.1.0 - - name: PHP syntax checker 5.6 - uses: prestashop/github-action-php-lint/5.6@master - - name: PHP syntax checker 7.2 uses: prestashop/github-action-php-lint/7.2@master @@ -27,6 +24,9 @@ jobs: - name: PHP syntax checker 8.1 uses: prestashop/github-action-php-lint/8.1@master + - name: PHP syntax checker 8.2 + uses: prestashop/github-action-php-lint/8.2@master + # Check the PHP code follow the coding standards php-cs-fixer: name: PHP-CS-Fixer @@ -58,7 +58,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - presta-versions: ['1.7.6', '1.7.7', '1.7.8', 'latest'] + presta-versions: ['1.7.7', '1.7.8', '8.0, 'latest'] steps: - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/tests/phpstan/phpstan-1.7.6.neon b/tests/phpstan/phpstan-1.7.6.neon deleted file mode 100644 index 914f475f..00000000 --- a/tests/phpstan/phpstan-1.7.6.neon +++ /dev/null @@ -1,15 +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.#' - - '#Parameter \#1 \$idCategory of class Category constructor expects null, int given.#' - - '#Parameter \#1 \$value of method ControllerCore::ajaxRender\(\) expects null, string\|false given.#' - - '#Parameter \#2 \$value of static method CacheCore::store\(\) expects string, array\|mysqli_result\|PDOStatement\|resource\|false\|null given.#' - - - message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#' - path: ../../productcomments.php \ No newline at end of file diff --git a/tests/phpstan/phpstan-8.0.neon b/tests/phpstan/phpstan-8.0.neon new file mode 100644 index 00000000..d96955ed --- /dev/null +++ b/tests/phpstan/phpstan-8.0.neon @@ -0,0 +1,8 @@ +includes: + - %currentWorkingDirectory%/tests/phpstan/phpstan.neon + +parameters: + ignoreErrors: + - + message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#' + path: ../../productcomments.php \ No newline at end of file From 865ec2cbf363621884f34b8082c3357c298d9957 Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Sat, 15 Jul 2023 07:16:57 +0700 Subject: [PATCH 17/27] typo --- .github/workflows/php.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index c2c5e881..10a1df75 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -58,7 +58,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - presta-versions: ['1.7.7', '1.7.8', '8.0, 'latest'] + presta-versions: ['1.7.7', '1.7.8', '8.0', 'latest'] steps: - name: Setup PHP uses: shivammathur/setup-php@v2 From ece3949638dae8a07652c1c94c46f164c89ee13f Mon Sep 17 00:00:00 2001 From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com> Date: Sat, 15 Jul 2023 07:25:19 +0700 Subject: [PATCH 18/27] ignore error from doctrine in obsolte phpstan --- tests/phpstan/phpstan-8.0.neon | 5 +---- tests/phpstan/phpstan.neon | 8 ++++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/phpstan/phpstan-8.0.neon b/tests/phpstan/phpstan-8.0.neon index d96955ed..19996b52 100644 --- a/tests/phpstan/phpstan-8.0.neon +++ b/tests/phpstan/phpstan-8.0.neon @@ -2,7 +2,4 @@ includes: - %currentWorkingDirectory%/tests/phpstan/phpstan.neon parameters: - ignoreErrors: - - - message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#' - path: ../../productcomments.php \ No newline at end of file + ignoreErrors: \ No newline at end of file diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon index b6d98be7..4a31b984 100644 --- a/tests/phpstan/phpstan.neon +++ b/tests/phpstan/phpstan.neon @@ -13,4 +13,12 @@ parameters: - message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#' path: ../../productcomments.php + - + message: '#PHPDoc tag @extends contains generic type + Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository
 but      
+         class                                                                  
+         Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository is   
+         not generic.#'
+      path: ../../src/Repository
   level: 5

From ac1afc9a2e4419e37cfe74939b09560e2cbf331e Mon Sep 17 00:00:00 2001
From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com>
Date: Sat, 15 Jul 2023 07:30:40 +0700
Subject: [PATCH 19/27] line break

---
 tests/phpstan/phpstan.neon | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon
index 4a31b984..bee26532 100644
--- a/tests/phpstan/phpstan.neon
+++ b/tests/phpstan/phpstan.neon
@@ -14,11 +14,6 @@ parameters:
       message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#'
       path: ../../productcomments.php
     - 
-      message: '#PHPDoc tag @extends contains generic type                              
-         Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository
 but      
-         class                                                                  
-         Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository is   
-         not generic.#'
+      message: '#PHPDoc tag @extends contains generic type Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository[a-zA-Z\\_]+ not generic.#'
       path: ../../src/Repository
   level: 5

From c28b142e4e141a7e002bbd474ea828bb1fd573c9 Mon Sep 17 00:00:00 2001
From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com>
Date: Sat, 15 Jul 2023 07:35:36 +0700
Subject: [PATCH 20/27] correct patern

---
 tests/phpstan/phpstan.neon | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon
index bee26532..328d7a46 100644
--- a/tests/phpstan/phpstan.neon
+++ b/tests/phpstan/phpstan.neon
@@ -14,6 +14,6 @@ parameters:
       message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#'
       path: ../../productcomments.php
     - 
-      message: '#PHPDoc tag @extends contains generic type Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository[a-zA-Z\\_]+ not generic.#'
+      message: '#PHPDoc tag @extends contains generic type Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<[a-zA-Z\\_]+> [a-zA-Z\\_]+ is not generic.#'
       path: ../../src/Repository
   level: 5

From 7fd091813084546704a150353231f59bf2f0ae9e Mon Sep 17 00:00:00 2001
From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com>
Date: Sat, 15 Jul 2023 07:42:12 +0700
Subject: [PATCH 21/27] ServiceEntityRepository error happens only in PS 1.7.6
 and 1.7.8

---
 tests/phpstan/phpstan-1.7.7.neon | 3 +++
 tests/phpstan/phpstan-1.7.8.neon | 3 +++
 tests/phpstan/phpstan.neon       | 3 ---
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/tests/phpstan/phpstan-1.7.7.neon b/tests/phpstan/phpstan-1.7.7.neon
index 341e5dc8..ffd0ba84 100644
--- a/tests/phpstan/phpstan-1.7.7.neon
+++ b/tests/phpstan/phpstan-1.7.7.neon
@@ -8,3 +8,6 @@ parameters:
     - '#Access to an undefined property HelperList::\$list_id.#'
     - '#Access to an undefined property HelperList::\$shopLinkType.#'
     - '#Parameter \#1 \$value of method ControllerCore::ajaxRender\(\) expects null, string\|false given.#'
+    - 
+      message: '#PHPDoc tag @extends contains generic type Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<[a-zA-Z\\_]+> [a-zA-Z\\_]+ is not generic.#'
+      path: ../../src/Repository    
diff --git a/tests/phpstan/phpstan-1.7.8.neon b/tests/phpstan/phpstan-1.7.8.neon
index d29f77ca..d2db3232 100644
--- a/tests/phpstan/phpstan-1.7.8.neon
+++ b/tests/phpstan/phpstan-1.7.8.neon
@@ -7,3 +7,6 @@ parameters:
     - '#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 Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<[a-zA-Z\\_]+> [a-zA-Z\\_]+ is not generic.#'
+      path: ../../src/Repository
diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon
index 328d7a46..b6d98be7 100644
--- a/tests/phpstan/phpstan.neon
+++ b/tests/phpstan/phpstan.neon
@@ -13,7 +13,4 @@ parameters:
     - 
       message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#'
       path: ../../productcomments.php
-    - 
-      message: '#PHPDoc tag @extends contains generic type Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<[a-zA-Z\\_]+> [a-zA-Z\\_]+ is not generic.#'
-      path: ../../src/Repository
   level: 5

From 3454bc7ff26d7ebf9b3bce80e6279149f62ad413 Mon Sep 17 00:00:00 2001
From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com>
Date: Mon, 24 Jul 2023 14:17:00 +0700
Subject: [PATCH 22/27] complete migration

---
 ProductCommentCriterion.php                   |   8 +
 productcomments.php                           | 131 ++++++------
 src/Entity/ProductCommentCriterion.php        | 103 ++++++++++
 .../ProductCommentCriterionRepository.php     | 187 +++++++++++++++++-
 src/Repository/ProductCommentRepository.php   |   2 -
 tests/phpstan/phpstan-1.7.7.neon              |   3 -
 tests/phpstan/phpstan-1.7.8.neon              |   3 -
 tests/phpstan/phpstan.neon                    |  15 +-
 8 files changed, 376 insertions(+), 76 deletions(-)

diff --git a/ProductCommentCriterion.php b/ProductCommentCriterion.php
index 88d5379d..7e412aaa 100644
--- a/ProductCommentCriterion.php
+++ b/ProductCommentCriterion.php
@@ -130,6 +130,8 @@ public function addCategory($id_category)
      * Add grade to a criterion
      *
      * @return bool succeed
+     *
+     * @deprecated 4.0.0
      */
     public function addGrade($id_product_comment, $grade)
     {
@@ -266,6 +268,9 @@ public function getCategories()
         return $criterions;
     }
 
+    /**
+     * @deprecated 6.0.0
+     */
     public function deleteCategories()
     {
         return Db::getInstance()->execute('
@@ -273,6 +278,9 @@ public function deleteCategories()
 			WHERE `id_product_comment_criterion` = ' . (int) $this->id);
     }
 
+    /**
+     * @deprecated 6.0.0
+     */
     public function deleteProducts()
     {
         return Db::getInstance()->execute('
diff --git a/productcomments.php b/productcomments.php
index 6ec5b669..58c4ea3a 100644
--- a/productcomments.php
+++ b/productcomments.php
@@ -28,6 +28,7 @@
     exit;
 }
 
+use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterion;
 use PrestaShop\PrestaShop\Core\Module\WidgetInterface;
 
 class ProductComments extends Module implements WidgetInterface
@@ -167,6 +168,10 @@ public function getCacheId($id_product = null)
 
     protected function _postProcess()
     {
+        $id_product_comment = (int) Tools::getValue('id_product_comment');
+        $commentRepository = $this->get('product_comment_repository');
+        $criterionRepository = $this->get('product_comment_criterion_repository');
+
         if (Tools::isSubmit('submitModerate')) {
             $errors = [];
             $productCommentsMinimalTime = Tools::getValue('PRODUCT_COMMENTS_MINIMAL_TIME');
@@ -197,76 +202,70 @@ protected function _postProcess()
                 $this->_html .= $this->displayConfirmation($this->trans('Settings updated', [], 'Modules.Productcomments.Admin'));
             }
         } elseif (Tools::isSubmit('productcomments')) {
-            $id_product_comment = (int) Tools::getValue('id_product_comment');
-            $comment = $this->get('product_comment_repository')->find($id_product_comment);
-            $this->get('product_comment_repository')->validate('1', $comment);
-            $this->get('product_comment_repository')->deleteReports($id_product_comment);
+            $comment = $commentRepository->find($id_product_comment);
+            $commentRepository->validate('1', $comment);
+            $commentRepository->deleteReports($id_product_comment);
         } elseif (Tools::isSubmit('deleteproductcomments')) {
-            $id_product_comment = (int) Tools::getValue('id_product_comment');
-            $comment = $this->get('product_comment_repository')->find($id_product_comment);
-            $this->get('product_comment_repository')->remove($comment, true);
+            $comment = $$commentRepository->find($id_product_comment);
+            $commentRepository->delete($comment);
         } elseif (Tools::isSubmit('submitEditCriterion')) {
+            /*
             $criterion = new ProductCommentCriterion((int) Tools::getValue('id_product_comment_criterion'));
             $criterion->id_product_comment_criterion_type = (int) Tools::getValue('id_product_comment_criterion_type');
             $criterion->active = Tools::getValue('active');
+            */
+            $criterion = $criterionRepository->findRelation((int) Tools::getValue('id_product_comment_criterion'));
+            file_put_contents('khoachemgio', print_r($criterion, true));
+            $criterion->setType((int) Tools::getValue('id_product_comment_criterion_type'));
+            $criterion->setActive(Tools::getValue('active'));
 
             $languages = Language::getLanguages();
             $name = [];
             foreach ($languages as $key => $value) {
                 $name[$value['id_lang']] = Tools::getValue('name_' . $value['id_lang']);
             }
-            $criterion->name = $name;
+            $criterion->setNames($name);
 
-            if (!$criterion->validateFields(false) || !$criterion->validateFieldsLang(false)) {
+            if (!$criterion->isValid()) {
                 $this->_html .= $this->displayError($this->trans('The criterion cannot be saved', [], 'Modules.Productcomments.Admin'));
             } else {
-                $criterion->save();
-
-                // Clear before reinserting data
-                $criterion->deleteCategories();
-                $criterion->deleteProducts();
-                if ($criterion->id_product_comment_criterion_type == 2) {
-                    if ($categories = Tools::getValue('categoryBox')) {
-                        if (count($categories)) {
-                            foreach ($categories as $id_category) {
-                                $criterion->addCategory((int) $id_category);
-                            }
-                        }
-                    }
-                } elseif ($criterion->id_product_comment_criterion_type == 3) {
-                    if ($products = Tools::getValue('ids_product')) {
-                        if (count($products)) {
-                            foreach ($products as $product) {
-                                $criterion->addProduct((int) $product);
-                            }
-                        }
-                    }
-                }
-                if ($criterion->save()) {
+                $criterion->setCategories(Tools::getValue('categoryBox'));
+                $criterion->setProducts(Tools::getValue('ids_product'));
+                if ($criterionRepository->update($criterion)) {
                     Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name, 'conf' => 4]));
                 } else {
                     $this->_html .= $this->displayError($this->trans('The criterion cannot be saved', [], 'Modules.Productcomments.Admin'));
                 }
             }
         } elseif (Tools::isSubmit('deleteproductcommentscriterion')) {
+            /*
             $productCommentCriterion = new ProductCommentCriterion((int) Tools::getValue('id_product_comment_criterion'));
             if ($productCommentCriterion->id) {
                 if ($productCommentCriterion->delete()) {
                     $this->_html .= $this->displayConfirmation($this->trans('Criterion deleted', [], 'Modules.Productcomments.Admin'));
                 }
             }
+            */
+            $criterion = $criterionRepository->findRelation((int) Tools::getValue('id_product_comment_criterion'));
+            if ($criterionRepository->delete($criterion)) {
+                $this->_html .= $this->displayConfirmation($this->trans('Criterion deleted', [], 'Modules.Productcomments.Admin'));
+            }
         } elseif (Tools::isSubmit('statusproductcommentscriterion')) {
+            /*
             $criterion = new ProductCommentCriterion((int) Tools::getValue('id_product_comment_criterion'));
             if ($criterion->id) {
                 $criterion->active = (int) (!$criterion->active);
                 $criterion->save();
             }
+            */
+            $criterion = $criterionRepository->findRelation((int) Tools::getValue('id_product_comment_criterion'));
+            $criterion->setActive(!$criterion->isActive());
             Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name, 'tab_module' => $this->tab, 'conf' => 4, 'module_name' => $this->name]));
         } elseif ($id_product_comment = (int) Tools::getValue('approveComment')) {
-            $comment = $this->get('product_comment_repository')->find($id_product_comment);
-            $this->get('product_comment_repository')->validate('1', $comment);
+            $comment = $commentRepository->find($id_product_comment);
+            $commentRepository->validate('1', $comment);
         } elseif ($id_product_comment = (int) Tools::getValue('noabuseComment')) {
-            $this->get('product_comment_repository')->deleteReports($id_product_comment);
+            $commentRepository->deleteReports($id_product_comment);
             Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name]));
         }
 
@@ -275,8 +274,6 @@ protected function _postProcess()
 
     public function getContent()
     {
-        include_once dirname(__FILE__) . '/ProductCommentCriterion.php';
-
         $this->_html = '';
         if (Tools::isSubmit('updateproductcommentscriterion')) {
             $this->_html .= $this->renderCriterionForm((int) Tools::getValue('id_product_comment_criterion'));
@@ -435,9 +432,10 @@ public function renderConfigForm()
     public function renderModerateLists()
     {
         $return = null;
+        $commentRepository = $this->get('product_comment_repository');
 
         if (Configuration::get('PRODUCT_COMMENTS_MODERATE')) {
-            $comments = $this->get('product_comment_repository')->getByValidate($this->langId, $this->shopId, 0, false);
+            $comments = $commentRepository->getByValidate($this->langId, $this->shopId, 0, false);
 
             $fields_list = $this->getStandardFieldList();
 
@@ -462,7 +460,7 @@ public function renderModerateLists()
             $return .= $helper->generateList($comments, $fields_list);
         }
 
-        $comments = $this->get('product_comment_repository')->getReportedComments($this->langId, $this->shopId);
+        $comments = $commentRepository->getReportedComments($this->langId, $this->shopId);
 
         $fields_list = $this->getStandardFieldList();
 
@@ -589,16 +587,17 @@ public function renderCommentsList()
         $helper->currentIndex = AdminController::$currentIndex . '&configure=' . $this->name;
         $helper->no_link = true;
 
-        $page = ($page = Tools::getValue('submitFilter' . $helper->list_id)) ? $page : 1;
-        $pagination = ($pagination = Tools::getValue($helper->list_id . '_pagination')) ? $pagination : 50;
+        $page = ($page = Tools::getValue('submitFilter' . $helper->list_id)) ? (int) $page : 1;
+        $pagination = ($pagination = Tools::getValue($helper->list_id . '_pagination')) ? (int) $pagination : 50;
 
         $moderate = Configuration::get('PRODUCT_COMMENTS_MODERATE');
+        $commentRepository = $this->get('product_comment_repository');
         if (empty($moderate)) {
-            $comments = $this->get('product_comment_repository')->getByValidate($this->langId, $this->shopId, 0, false, (int) $page, (int) $pagination, true);
-            $count = $this->get('product_comment_repository')->getCountByValidate(0, true);
+            $comments = $commentRepository->getByValidate($this->langId, $this->shopId, 0, false, $page, $pagination, true);
+            $count = $commentRepository->getCountByValidate(0, true);
         } else {
-            $comments = $this->get('product_comment_repository')->getByValidate($this->langId, $this->shopId, 1, false, (int) $page, (int) $pagination);
-            $count = $this->get('product_comment_repository')->getCountByValidate(1);
+            $comments = $commentRepository->getByValidate($this->langId, $this->shopId, 1, false, $page, $pagination);
+            $count = $commentRepository->getCountByValidate(1);
         }
 
         $helper->listTotal = $count;
@@ -620,6 +619,7 @@ public function getConfigFieldsValues()
 
     public function getCriterionFieldsValues($id = 0)
     {
+        /*
         $criterion = new ProductCommentCriterion($id);
 
         return [
@@ -628,6 +628,17 @@ public function getCriterionFieldsValues($id = 0)
             'active' => $criterion->active,
             'id_product_comment_criterion' => $criterion->id,
         ];
+        */
+
+        $criterionRepos = $this->get('product_comment_criterion_repository');
+        $criterion = $criterionRepos->findRelation($id);
+
+        return [
+            'name' => $criterion->getNames(),
+            'id_product_comment_criterion_type' => $criterion->getType(),
+            'active' => $criterion->isActive(),
+            'id_product_comment_criterion' => $criterion->getId(),
+        ];
     }
 
     public function getStandardFieldList()
@@ -716,11 +727,13 @@ public function renderCriterionForm($id_criterion = 0)
         }
 
         $criterionRepository = $this->get('product_comment_criterion_repository');
-        $criterion = $criterionRepository->find((int) $id_criterion);
-        $selected_categories = $criterionRepository->getCategories($criterion);
+
+        $criterion = $criterionRepository->findRelation($id_criterion);
+        $selected_categories = $criterionRepository->getCategories($id_criterion);
 
         $product_table_values = Product::getSimpleProducts($this->langId);
-        $selected_products = $criterionRepository->getProducts($criterion);
+        $selected_products = $criterionRepository->getProducts($id_criterion);
+
         foreach ($product_table_values as $key => $product) {
             if (false !== array_search($product['id_product'], $selected_products)) {
                 $product_table_values[$key]['selected'] = 1;
@@ -937,9 +950,9 @@ public function hookFilterProductContent(array $params)
         if (empty($params['object']->id)) {
             return $params;
         }
-        $productCommentRepository = $this->get('product_comment_repository');
-        $averageRating = $productCommentRepository->getAverageGrade($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE'));
-        $nbComments = $productCommentRepository->getCommentsNumber($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE'));
+        $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 */
         $params['object']->productComments = [
@@ -962,10 +975,10 @@ public function hookFilterProductContent(array $params)
      */
     private function renderProductCommentsList($product)
     {
-        $productCommentRepository = $this->get('product_comment_repository');
-        $averageGrade = $productCommentRepository->getAverageGrade($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE'));
-        $commentsNb = $productCommentRepository->getCommentsNumber($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE'));
-        $isPostAllowed = $productCommentRepository->isPostAllowed($product->id, (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest);
+        $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'));
+        $isPostAllowed = $commentRepository->isPostAllowed($product->id, (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest);
 
         /* configure pagination */
         $commentsTotalPages = 0;
@@ -1031,10 +1044,10 @@ private function renderProductCommentModal($product)
 
     public function getWidgetVariables($hookName = null, array $configuration = [])
     {
-        $productCommentRepository = $this->get('product_comment_repository');
-        $averageGrade = $productCommentRepository->getAverageGrade($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE'));
-        $commentsNb = $productCommentRepository->getCommentsNumber($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE'));
-        $isPostAllowed = $productCommentRepository->isPostAllowed($configuration['id_product'], (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest);
+        $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'));
+        $isPostAllowed = $commentRepository->isPostAllowed($configuration['id_product'], (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest);
 
         return [
             'average_grade' => $averageGrade,
diff --git a/src/Entity/ProductCommentCriterion.php b/src/Entity/ProductCommentCriterion.php
index b3ea724b..b2d5d2e7 100644
--- a/src/Entity/ProductCommentCriterion.php
+++ b/src/Entity/ProductCommentCriterion.php
@@ -27,6 +27,8 @@
 namespace PrestaShop\Module\ProductComment\Entity;
 
 use Doctrine\ORM\Mapping as ORM;
+use Language;
+use Validate;
 
 /**
  * @ORM\Table()
@@ -34,6 +36,7 @@
  */
 class ProductCommentCriterion
 {
+    const NAME_MAX_LENGTH = 64;
     const ENTIRE_CATALOG_TYPE = 1;
     const CATEGORIES_TYPE = 2;
     const PRODUCTS_TYPE = 3;
@@ -61,6 +64,93 @@ class ProductCommentCriterion
      */
     private $active = false;
 
+    /**
+     * @var array
+     *            Need to be implemented as ORM\OneToMany in the future
+     */
+    private $names;
+
+    /**
+     * @var array
+     *            Need to be implemented as ORM\OneToMany in the future
+     */
+    private $categories;
+
+    /**
+     * @var array
+     *            Need to be implemented as ORM\OneToMany in the future
+     */
+    private $products;
+
+    public function __construct()
+    {
+        $langIsoIds = Language::getIsoIds();
+        $langString = '';
+        foreach ($langIsoIds as $langIsoId) {
+            $this->names[$langIsoId['id_lang']] = $langIsoId['iso_code'];
+        }
+    }
+
+    /**
+     * @return array
+     */
+    public function getNames()
+    {
+        return $this->names;
+    }
+
+    /**
+     * @param array $langNames
+     *
+     * @return ProductCommentCriterion
+     */
+    public function setNames($langNames)
+    {
+        $this->names = $langNames;
+
+        return $this;
+    }
+
+    /**
+     * @return array
+     */
+    public function getCategories()
+    {
+        return $this->categories;
+    }
+
+    /**
+     * @param array $selectedCategories
+     *
+     * @return ProductCommentCriterion
+     */
+    public function setCategories($selectedCategories)
+    {
+        $this->categories = $selectedCategories;
+
+        return $this;
+    }
+
+    /**
+     * @return array
+     */
+    public function getProducts()
+    {
+        return $this->products;
+    }
+
+    /**
+     * @param array $selectedProducts
+     *
+     * @return ProductCommentCriterion
+     */
+    public function setProducts($selectedProducts)
+    {
+        $this->products = $selectedProducts;
+
+        return $this;
+    }
+
     /**
      * @return int
      */
@@ -108,4 +198,17 @@ public function setActive($active)
 
         return $this;
     }
+
+    /**
+     * @return bool
+     */
+    public function isValid()
+    {
+        $res = true;
+        foreach ($this->names as $key => $value) {
+            $res &= Validate::isGenericName($value);
+        }
+
+        return $res;
+    }
 }
diff --git a/src/Repository/ProductCommentCriterionRepository.php b/src/Repository/ProductCommentCriterionRepository.php
index c5a3bdf5..de214acd 100644
--- a/src/Repository/ProductCommentCriterionRepository.php
+++ b/src/Repository/ProductCommentCriterionRepository.php
@@ -70,6 +70,154 @@ public function __construct($registry, $connection, $databasePrefix)
         $this->databasePrefix = $databasePrefix;
     }
 
+    public function add(ProductCommentCriterion $entity, bool $flush = false): void
+    {
+        $this->getEntityManager()->persist($entity);
+
+        if ($flush) {
+            $this->getEntityManager()->flush();
+        }
+    }
+
+    public function remove(ProductCommentCriterion $entity, bool $flush = false): void
+    {
+        $this->getEntityManager()->remove($entity);
+
+        if ($flush) {
+            $this->getEntityManager()->flush();
+        }
+    }
+
+    private function deleteLangs($criterion): int
+    {
+        return $this->connection->executeUpdate('
+			DELETE FROM `' . _DB_PREFIX_ . 'product_comment_criterion_lang`
+			WHERE `id_product_comment_criterion` = ' . $criterion->getId());
+    }
+
+    private function deleteCategories($criterion): int
+    {
+        return $this->connection->executeUpdate('
+			DELETE FROM `' . _DB_PREFIX_ . 'product_comment_criterion_category`
+			WHERE `id_product_comment_criterion` = ' . $criterion->getId());
+    }
+
+    private function deleteProducts($criterion): int
+    {
+        return $this->connection->executeUpdate('
+			DELETE FROM `' . _DB_PREFIX_ . 'product_comment_criterion_product`
+			WHERE `id_product_comment_criterion` = ' . $criterion->getId());
+    }
+
+    private function deleteGrades($criterion): int
+    {
+        return $this->connection->executeUpdate('
+			DELETE FROM `' . _DB_PREFIX_ . 'product_comment_criterion_grade`
+			WHERE `id_product_comment_criterion` = ' . $criterion->getId());
+    }
+
+    /* Remove a criterion and Delete its manual relation _lang, _category, _product, _grade */
+    public function delete(ProductCommentCriterion $criterion): int
+    {
+        $res = 0;
+
+        $criterionType = $criterion->getType();
+
+        $this->remove($criterion, true);
+        $this->getEntityManager()->flush();
+
+        $res += $this->deleteLangs($criterion);
+
+        if ($criterionType == 2) {
+            $res += $this->deleteCategories($criterion);
+        } elseif ($criterionType == 3) {
+            $res += $this->deleteProducts($criterion);
+        }
+
+        $res += $this->deleteGrades($criterion);
+
+        return $res;
+    }
+
+    /* Update a criterion and Delete its manual relation _lang, _category, _product, _grade */
+    public function update(ProductCommentCriterion $criterion): int
+    {
+        $res = 0;
+
+        $criterionType = $criterion->getType();
+
+        $this->getEntityManager()->persist($criterion);
+        $this->getEntityManager()->flush();
+
+        $res += $this->deleteLangs($criterion);
+        $res += $this->updateLangs($criterion);
+
+        if ($criterionType == 2) {
+            $res += $this->deleteCategories($criterion);
+            $res += $this->updateCategories($criterion);
+        } elseif ($criterionType == 3) {
+            $res += $this->deleteProducts($criterion);
+            $res += $this->updateProducts($criterion);
+        }
+
+        return $res;
+    }
+
+    private function updateLangs($criterion): int
+    {
+        $res = 0;
+        $criterionId = $criterion->getId();
+        foreach ($criterion->getNames() as $key => $value) {
+            $qb = $this->connection->createQueryBuilder();
+            $qb
+            ->insert(_DB_PREFIX_ . 'product_comment_criterion_lang')
+            ->values(
+                [
+                    'id_product_comment_criterion' => '?',
+                    'id_lang' => '?',
+                    'name' => '?',
+                ]
+            )
+            ->setParameter(0, $criterionId)
+            ->setParameter(1, $key)
+            ->setParameter(2, $value)
+            ;
+            $res += $this->connection->executeUpdate($qb->getSQL(), $qb->getParameters(), $qb->getParameterTypes());
+        }
+
+        return $res;
+    }
+
+    private function updateCategories($criterion): int
+    {
+        $res = 0;
+        $criterionId = $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 . ')'
+            );
+        }
+
+        return $res;
+    }
+
+    private function updateProducts($criterion): int
+    {
+        $res = 0;
+        $criterionId = $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 . ')'
+            );
+        }
+
+        return $res;
+    }
+
     /**
      * @param int $idProduct
      * @param int $idLang
@@ -131,16 +279,16 @@ public function getCriterions($id_lang, $type = false, $active = false)
     }
 
     /**
-     * @param ProductCommentCriterion $entity
+     * @param int $id_criterion
      *
      * @return array
      */
-    public function getProducts($entity)
+    public function getProducts(int $id_criterion)
     {
         $sql = '
 			SELECT pccp.id_product, pccp.id_product_comment_criterion
 			FROM `' . _DB_PREFIX_ . 'product_comment_criterion_product` pccp
-			WHERE pccp.id_product_comment_criterion = ' . $entity->getId();
+			WHERE pccp.id_product_comment_criterion = ' . $id_criterion;
 
         $res = $this->connection->executeQuery($sql)->fetchAll();
 
@@ -155,16 +303,16 @@ public function getProducts($entity)
     }
 
     /**
-     * @param ProductCommentCriterion $entity
+     * @param int $id_criterion
      *
      * @return array
      */
-    public function getCategories(ProductCommentCriterion $entity)
+    public function getCategories(int $id_criterion)
     {
         $sql = '
 			SELECT pccc.id_category, pccc.id_product_comment_criterion
 			FROM `' . _DB_PREFIX_ . 'product_comment_criterion_category` pccc
-			WHERE pccc.id_product_comment_criterion = ' . $entity->getId();
+			WHERE pccc.id_product_comment_criterion = ' . $id_criterion;
 
         $res = $this->connection->executeQuery($sql)->fetchAll();
 
@@ -191,4 +339,31 @@ public function getTypes()
             3 => $sfTranslator->trans('Restricted to some products', [], 'Modules.Productcomments.Admin'),
         ];
     }
+
+    /**
+     * Get Criterion with names in ative languages
+     *
+     * @return ProductCommentCriterion
+     */
+    public function findRelation($id_criterion)
+    {
+        if ($id_criterion > 0) {
+            $criterion = $this->find($id_criterion);
+            $sql = '
+			SELECT `id_lang`, `name`
+			FROM `' . _DB_PREFIX_ . 'product_comment_criterion_lang` pccl			
+			WHERE pccl.id_product_comment_criterion = ' . $id_criterion . '
+			ORDER BY pccl.`id_lang` ASC';
+            $langNames = $this->connection->executeQuery($sql)->fetchAll();
+            $langArray = [];
+            foreach ($langNames as $langName) {
+                $langArray[$langName['id_lang']] = $langName['name'];
+            }
+            $criterion->setNames($langArray);
+        } else {
+            $criterion = new ProductCommentCriterion();
+        }
+
+        return $criterion;
+    }
 }
diff --git a/src/Repository/ProductCommentRepository.php b/src/Repository/ProductCommentRepository.php
index 4ec08baf..a5d334e2 100644
--- a/src/Repository/ProductCommentRepository.php
+++ b/src/Repository/ProductCommentRepository.php
@@ -401,8 +401,6 @@ public function getCommentsNumberForProducts(array $productIds, $validatedOnly)
 
         $sql .= ' FROM ' . $this->databasePrefix . 'product_comment';
 
-        // return $sql;
-
         $query = $this->connection->prepare($sql);
         $query->execute();
 
diff --git a/tests/phpstan/phpstan-1.7.7.neon b/tests/phpstan/phpstan-1.7.7.neon
index ffd0ba84..341e5dc8 100644
--- a/tests/phpstan/phpstan-1.7.7.neon
+++ b/tests/phpstan/phpstan-1.7.7.neon
@@ -8,6 +8,3 @@ parameters:
     - '#Access to an undefined property HelperList::\$list_id.#'
     - '#Access to an undefined property HelperList::\$shopLinkType.#'
     - '#Parameter \#1 \$value of method ControllerCore::ajaxRender\(\) expects null, string\|false given.#'
-    - 
-      message: '#PHPDoc tag @extends contains generic type Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<[a-zA-Z\\_]+> [a-zA-Z\\_]+ is not generic.#'
-      path: ../../src/Repository    
diff --git a/tests/phpstan/phpstan-1.7.8.neon b/tests/phpstan/phpstan-1.7.8.neon
index d2db3232..d29f77ca 100644
--- a/tests/phpstan/phpstan-1.7.8.neon
+++ b/tests/phpstan/phpstan-1.7.8.neon
@@ -7,6 +7,3 @@ parameters:
     - '#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 Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<[a-zA-Z\\_]+> [a-zA-Z\\_]+ is not generic.#'
-      path: ../../src/Repository
diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon
index b6d98be7..f3c58dd2 100644
--- a/tests/phpstan/phpstan.neon
+++ b/tests/phpstan/phpstan.neon
@@ -11,6 +11,15 @@ parameters:
     - ../../upgrade/
   ignoreErrors:
     - 
-      message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#'
-      path: ../../productcomments.php
-  level: 5
+     message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#'
+     path: ../../productcomments.php
+    - 
+      message: '#Property .+::\$id is never written, only read.#'
+      path: ../../src/Entity/
+    - 
+      message: '#Property .+::\$grade is never read, only written.#'
+      path: ../../src/Entity/
+    - 
+      message: '#Property .+::\$registry is unused.#'
+      path: ../../src/Repository/
+  level: 5
\ No newline at end of file

From 7e1860fbf5075193e36b8fb1a8a3c6efaeaac4e1 Mon Sep 17 00:00:00 2001
From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com>
Date: Mon, 24 Jul 2023 14:30:16 +0700
Subject: [PATCH 23/27] resolve conflict

---
 .github/workflows/php.yml      | 8 ++++----
 productcomments.php            | 3 ---
 tests/phpstan/phpstan-8.0.neon | 2 +-
 3 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index 10a1df75..329fb2a1 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -3,7 +3,7 @@ on: [push, pull_request]
 jobs:
   # Check there is no syntax errors in the project
   php-linter:
-    name: PHP Syntax check 7.2 => 8.1
+    name: PHP Syntax check 7.2 => 8.2
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
@@ -25,7 +25,7 @@ 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        
 
   # Check the PHP code follow the coding standards
   php-cs-fixer:
@@ -50,7 +50,7 @@ jobs:
         run: composer install
 
       - name: Run PHP-CS-Fixer
-        run: ./vendor/bin/php-cs-fixer fix --dry-run --diff --using-cache=no --diff-format udiff
+        run: ./vendor/bin/php-cs-fixer fix --dry-run --diff --using-cache=no
 
   # Run PHPStan against the module and a PrestaShop release
   phpstan:
@@ -86,4 +86,4 @@ jobs:
 
       # 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: ./tests/phpstan.sh ${{ matrix.presta-versions }}
\ No newline at end of file
diff --git a/productcomments.php b/productcomments.php
index 58c4ea3a..6f996078 100644
--- a/productcomments.php
+++ b/productcomments.php
@@ -57,9 +57,6 @@ public function __construct()
         $this->displayName = $this->trans('Product Comments', [], 'Modules.Productcomments.Admin');
         $this->description = $this->trans('Allow users to post reviews on your products and/or rate them based on specific criteria.', [], 'Modules.Productcomments.Admin');
 
-        $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.7', 'max' => _PS_VERSION_];
     }
 
diff --git a/tests/phpstan/phpstan-8.0.neon b/tests/phpstan/phpstan-8.0.neon
index 19996b52..e71d43a6 100644
--- a/tests/phpstan/phpstan-8.0.neon
+++ b/tests/phpstan/phpstan-8.0.neon
@@ -1,5 +1,5 @@
 includes:
-  - %currentWorkingDirectory%/tests/phpstan/phpstan.neon
+	- %currentWorkingDirectory%/tests/phpstan/phpstan.neon
 
 parameters:
   ignoreErrors:
\ No newline at end of file

From b8cde07bd22597b5e3ded97890234bd57080a21d Mon Sep 17 00:00:00 2001
From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com>
Date: Mon, 24 Jul 2023 14:34:13 +0700
Subject: [PATCH 24/27] resolve conflict

---
 tests/phpstan/phpstan.neon | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon
index f3c58dd2..c72e7494 100644
--- a/tests/phpstan/phpstan.neon
+++ b/tests/phpstan/phpstan.neon
@@ -9,17 +9,17 @@ parameters:
     - ../../controllers/
     - ../../src/
     - ../../upgrade/
+  level: 5
   ignoreErrors:
-    - 
-     message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#'
-     path: ../../productcomments.php
-    - 
-      message: '#Property .+::\$id is never written, only read.#'
-      path: ../../src/Entity/
-    - 
-      message: '#Property .+::\$grade is never read, only written.#'
-      path: ../../src/Entity/
-    - 
-      message: '#Property .+::\$registry is unused.#'
-      path: ../../src/Repository/
-  level: 5
\ No newline at end of file
+  - 
+    message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#'
+    path: ../../productcomments.php
+  - 
+    message: '#Property .+::\$id is never written, only read.#'
+    path: ../../src/Entity/
+  - 
+    message: '#Property .+::\$grade is never read, only written.#'
+    path: ../../src/Entity/
+  - 
+    message: '#Property .+::\$registry is unused.#'
+    path: ../../src/Repository/
\ No newline at end of file

From 1c3e88c3e53a05b55f1782a8f2d4cf17e2dfbe77 Mon Sep 17 00:00:00 2001
From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com>
Date: Mon, 24 Jul 2023 14:37:19 +0700
Subject: [PATCH 25/27] resolve conflict

---
 tests/phpstan/phpstan-8.0.neon | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/phpstan/phpstan-8.0.neon b/tests/phpstan/phpstan-8.0.neon
index e71d43a6..23b71e8d 100644
--- a/tests/phpstan/phpstan-8.0.neon
+++ b/tests/phpstan/phpstan-8.0.neon
@@ -2,4 +2,4 @@ includes:
 	- %currentWorkingDirectory%/tests/phpstan/phpstan.neon
 
 parameters:
-  ignoreErrors:
\ No newline at end of file
+  ignoreErrors:

From db80adb5e0925caa31f56aa05ae264bc168e2d0e Mon Sep 17 00:00:00 2001
From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com>
Date: Mon, 24 Jul 2023 14:40:18 +0700
Subject: [PATCH 26/27] restore variable declarations

---
 productcomments.php | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/productcomments.php b/productcomments.php
index 6f996078..58c4ea3a 100644
--- a/productcomments.php
+++ b/productcomments.php
@@ -57,6 +57,9 @@ public function __construct()
         $this->displayName = $this->trans('Product Comments', [], 'Modules.Productcomments.Admin');
         $this->description = $this->trans('Allow users to post reviews on your products and/or rate them based on specific criteria.', [], 'Modules.Productcomments.Admin');
 
+        $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.7', 'max' => _PS_VERSION_];
     }
 

From 1e63d939e77c1bb7e006dc0a401ec99c885b49ae Mon Sep 17 00:00:00 2001
From: leemyong pakvn <3759923+leemyongpakvn@users.noreply.github.com>
Date: Mon, 24 Jul 2023 14:46:56 +0700
Subject: [PATCH 27/27] resolve conflict

---
 productcomments.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/productcomments.php b/productcomments.php
index 58c4ea3a..651e9609 100644
--- a/productcomments.php
+++ b/productcomments.php
@@ -57,10 +57,10 @@ public function __construct()
         $this->displayName = $this->trans('Product Comments', [], 'Modules.Productcomments.Admin');
         $this->description = $this->trans('Allow users to post reviews on your products and/or rate them based on specific criteria.', [], 'Modules.Productcomments.Admin');
 
+        $this->ps_versions_compliancy = ['min' => '1.7.7', 'max' => _PS_VERSION_];
+
         $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.7', 'max' => _PS_VERSION_];
     }
 
     public function install($keep = true)