diff --git a/ProductComment.php b/ProductComment.php index f3fc56a6..53cca302 100644 --- a/ProductComment.php +++ b/ProductComment.php @@ -438,6 +438,8 @@ public static function deleteUsefulness($id_product_comment) * Report comment * * @return bool + * + * @deprecated 4.0.0 - migrated to controllers/front/ReportComment and src/Entity/ProductCommentReport */ public static function reportComment($id_product_comment, $id_customer) { @@ -450,6 +452,8 @@ public static function reportComment($id_product_comment, $id_customer) * Comment already report * * @return bool + * + * @deprecated 4.0.0 - migrated to controllers/front/ReportComment and src/Entity/ProductCommentReport */ public static function isAlreadyReport($id_product_comment, $id_customer) { @@ -464,6 +468,8 @@ public static function isAlreadyReport($id_product_comment, $id_customer) * Set comment usefulness * * @return bool + * + * @deprecated 4.0.0 - migrated to controllers/front/UpdateCommentUsefulness and src/Entity/ProductCommentUsefulness */ public static function setCommentUsefulness($id_product_comment, $usefulness, $id_customer) { @@ -476,6 +482,8 @@ public static function setCommentUsefulness($id_product_comment, $usefulness, $i * Usefulness already set * * @return bool + * + * @deprecated 4.0.0 - migrated to controllers/front/UpdateCommentUsefulness and src/Entity/ProductCommentUsefulness */ public static function isAlreadyUsefulness($id_product_comment, $id_customer) { diff --git a/ProductCommentCriterion.php b/ProductCommentCriterion.php index 7e412aaa..1ae4df3f 100644 --- a/ProductCommentCriterion.php +++ b/ProductCommentCriterion.php @@ -47,6 +47,9 @@ class ProductCommentCriterion extends ObjectModel ], ]; + /** + * @deprecated 6.0.0 - migrated to src/Repository/ProductCommentCriterionRepository + */ public function delete() { if (!parent::delete()) { @@ -96,6 +99,8 @@ public function update($nullValues = false) * Link a Comment Criterion to a product * * @return bool succeed + * + * @deprecated 6.0.0 - migrated to src/Repository/ProductCommentCriterionRepository */ public function addProduct($id_product) { @@ -113,6 +118,8 @@ public function addProduct($id_product) * Link a Comment Criterion to a category * * @return bool succeed + * + * @deprecated 6.0.0 - migrated to src/Repository/ProductCommentCriterionRepository */ public function addCategory($id_category) { @@ -165,13 +172,6 @@ public static function getByProduct($id_product, $id_lang) !Validate::isUnsignedId($id_lang)) { exit(Tools::displayError()); } - $alias = 'p'; - $table = ''; - // check if version > 1.5 to add shop association - if (version_compare(_PS_VERSION_, '1.5', '>')) { - $table = '_shop'; - $alias = 'ps'; - } $cache_id = 'ProductCommentCriterion::getByProduct_' . $id_product . '-' . $id_lang; if (!Cache::isStored($cache_id)) { @@ -184,8 +184,8 @@ public static function getByProduct($id_product, $id_lang) ON (pcc.`id_product_comment_criterion` = pccp.`id_product_comment_criterion` AND pccp.`id_product` = ' . $id_product . ') LEFT JOIN `' . _DB_PREFIX_ . 'product_comment_criterion_category` pccc ON (pcc.`id_product_comment_criterion` = pccc.`id_product_comment_criterion`) - LEFT JOIN `' . _DB_PREFIX_ . 'product' . $table . '` ' . $alias . ' - ON (' . $alias . '.id_category_default = pccc.id_category AND ' . $alias . '.id_product = ' . $id_product . ') + LEFT JOIN `' . _DB_PREFIX_ . 'product_shop` ps + ON (ps.id_category_default = pccc.id_category AND ps.id_product = ' . $id_product . ') WHERE pccl.`id_lang` = ' . $id_lang . ' AND ( pccp.id_product IS NOT NULL diff --git a/config.xml b/config.xml index b378a090..bba666f0 100644 --- a/config.xml +++ b/config.xml @@ -2,7 +2,7 @@ productcomments - + diff --git a/config/admin/services.yml b/config/admin/services.yml index 6e16e432..02ce511d 100644 --- a/config/admin/services.yml +++ b/config/admin/services.yml @@ -1,2 +1,18 @@ imports: - { resource: ../common.yml } + +services: + product_comment_criterion_form_data_provider: + class: 'PrestaShop\Module\ProductComment\Form\ProductCommentCriterionFormDataProvider' + public: true + arguments: + - '@product_comment_criterion_repository' + - '@prestashop.core.admin.lang.repository' + + product_comment_criterion_form_data_handler: + class: 'PrestaShop\Module\ProductComment\Form\ProductCommentCriterionFormDataHandler' + public: true + arguments: + - '@product_comment_criterion_repository' + - '@prestashop.core.admin.lang.repository' + - '@doctrine.orm.default_entity_manager' \ No newline at end of file diff --git a/install.sql b/install.sql index 53ee6cb6..bb775562 100644 --- a/install.sql +++ b/install.sql @@ -14,35 +14,35 @@ CREATE TABLE IF NOT EXISTS `PREFIX_product_comment` ( KEY `id_product` (`id_product`), KEY `id_customer` (`id_customer`), KEY `id_guest` (`id_guest`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS `PREFIX_product_comment_criterion` ( `id_product_comment_criterion` int(10) unsigned NOT NULL auto_increment, `id_product_comment_criterion_type` tinyint(1) NOT NULL, `active` tinyint(1) NOT NULL, PRIMARY KEY (`id_product_comment_criterion`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS `PREFIX_product_comment_criterion_product` ( `id_product` int(10) unsigned NOT NULL, `id_product_comment_criterion` int(10) unsigned NOT NULL, PRIMARY KEY(`id_product`, `id_product_comment_criterion`), KEY `id_product_comment_criterion` (`id_product_comment_criterion`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS `PREFIX_product_comment_criterion_lang` ( `id_product_comment_criterion` INT(11) UNSIGNED NOT NULL , `id_lang` INT(11) UNSIGNED NOT NULL , `name` VARCHAR(64) NOT NULL , PRIMARY KEY ( `id_product_comment_criterion` , `id_lang` ) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS `PREFIX_product_comment_criterion_category` ( `id_product_comment_criterion` int(10) unsigned NOT NULL, `id_category` int(10) unsigned NOT NULL, PRIMARY KEY(`id_product_comment_criterion`, `id_category`), KEY `id_category` (`id_category`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS `PREFIX_product_comment_grade` ( `id_product_comment` int(10) unsigned NOT NULL, @@ -50,20 +50,20 @@ CREATE TABLE IF NOT EXISTS `PREFIX_product_comment_grade` ( `grade` int(10) unsigned NOT NULL, PRIMARY KEY (`id_product_comment`, `id_product_comment_criterion`), KEY `id_product_comment_criterion` (`id_product_comment_criterion`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS `PREFIX_product_comment_usefulness` ( `id_product_comment` int(10) unsigned NOT NULL, `id_customer` int(10) unsigned NOT NULL, `usefulness` tinyint(1) unsigned NOT NULL, PRIMARY KEY (`id_product_comment`, `id_customer`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS `PREFIX_product_comment_report` ( `id_product_comment` int(10) unsigned NOT NULL, `id_customer` int(10) unsigned NOT NULL, PRIMARY KEY (`id_product_comment`, `id_customer`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8mb4; INSERT IGNORE INTO `PREFIX_product_comment_criterion` VALUES ('1', '1', '1'); diff --git a/productcomments.php b/productcomments.php index 74c44069..6d22ab0c 100644 --- a/productcomments.php +++ b/productcomments.php @@ -47,7 +47,7 @@ public function __construct() { $this->name = 'productcomments'; $this->tab = 'front_office_features'; - $this->version = '6.0.2'; + $this->version = '6.0.3'; $this->author = 'PrestaShop'; $this->need_instance = 0; $this->bootstrap = true; @@ -169,8 +169,10 @@ public function getCacheId($id_product = null) protected function _postProcess() { $id_product_comment = (int) Tools::getValue('id_product_comment'); + $id_product_comment_criterion = (int) Tools::getValue('id_product_comment_criterion'); $commentRepository = $this->get('product_comment_repository'); $criterionRepository = $this->get('product_comment_criterion_repository'); + $criterionFormHandler = $this->get('product_comment_criterion_form_data_handler'); if (Tools::isSubmit('submitModerate')) { $errors = []; @@ -207,9 +209,20 @@ protected function _postProcess() $commentRepository->deleteReports($id_product_comment); } elseif (Tools::isSubmit('deleteproductcomments')) { $comment = $commentRepository->find($id_product_comment); - $commentRepository->delete($comment); + + if ($comment === null) { + $this->_html .= $this->displayError($this->trans('The comment cannot be deleted', [], 'Modules.Productcomments.Admin')); + } else { + $commentRepository->delete($comment); + Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name])); + } } elseif (Tools::isSubmit('submitEditCriterion')) { - $criterion = $criterionRepository->findRelation((int) Tools::getValue('id_product_comment_criterion')); + if ($id_product_comment_criterion > 0) { + $criterion = $criterionRepository->find($id_product_comment_criterion); + } else { + $criterion = new ProductCommentCriterion(); + } + $criterion->setType((int) Tools::getValue('id_product_comment_criterion_type')); $criterion->setActive(Tools::getValue('active')); @@ -218,7 +231,12 @@ protected function _postProcess() foreach ($languages as $key => $value) { $name[$value['id_lang']] = Tools::getValue('name_' . $value['id_lang']); } - $criterion->setNames($name); + + if ($id_product_comment_criterion > 0) { + $criterionFormHandler->updateLangs($criterion, $name); + } else { + $criterionFormHandler->createLangs($criterion, $name); + } if (!$criterion->isValid()) { $this->_html .= $this->displayError($this->trans('The criterion cannot be saved', [], 'Modules.Productcomments.Admin')); @@ -232,14 +250,18 @@ protected function _postProcess() } } } elseif (Tools::isSubmit('deleteproductcommentscriterion')) { - $criterion = $criterionRepository->findRelation((int) Tools::getValue('id_product_comment_criterion')); + $criterion = $criterionRepository->find($id_product_comment_criterion); if ($criterionRepository->delete($criterion)) { - $this->_html .= $this->displayConfirmation($this->trans('Criterion deleted', [], 'Modules.Productcomments.Admin')); + Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name])); + } else { + $this->_html .= $this->displayError($this->trans('Criterion cannot be deleted', [], 'Modules.Productcomments.Admin')); } } elseif (Tools::isSubmit('statusproductcommentscriterion')) { - $criterion = $criterionRepository->findRelation((int) Tools::getValue('id_product_comment_criterion')); + $criterion = $criterionRepository->find($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])); + $criterionRepository->updateGeneral($criterion); + + Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name])); } elseif ($id_product_comment = (int) Tools::getValue('approveComment')) { $comment = $commentRepository->find($id_product_comment); $commentRepository->validate($comment, 1); @@ -596,16 +618,22 @@ public function getConfigFieldsValues() ]; } - public function getCriterionFieldsValues($id = 0) + public function getCriterionFieldsValues(int $id = 0) { $criterionRepos = $this->get('product_comment_criterion_repository'); - $criterion = $criterionRepos->findRelation($id); + $criterionFormProvider = $this->get('product_comment_criterion_form_data_provider'); + + if ($id > 0) { + $criterionData = $criterionFormProvider->getData($id); + } else { + $criterionData = $criterionFormProvider->getDefaultData(); + } return [ - 'name' => $criterion->getNames(), - 'id_product_comment_criterion_type' => $criterion->getType(), - 'active' => $criterion->isActive(), - 'id_product_comment_criterion' => $criterion->getId(), + 'name' => $criterionData['name'], + 'id_product_comment_criterion_type' => $criterionData['type'], + 'active' => $criterionData['active'], + 'id_product_comment_criterion' => $id, ]; } @@ -696,7 +724,7 @@ public function renderCriterionForm($id_criterion = 0) $criterionRepository = $this->get('product_comment_criterion_repository'); - $criterion = $criterionRepository->findRelation($id_criterion); + $criterion = $criterionRepository->find($id_criterion); $selected_categories = $criterionRepository->getCategories($id_criterion); $product_table_values = Product::getSimpleProducts($this->langId); @@ -1044,9 +1072,16 @@ public function renderWidget($hookName = null, array $configuration = []) $idProduct = $this->context->controller->getProduct()->id; $variables = $this->getWidgetVariables($hookName, ['id_product' => $idProduct]); - $filePath = 'quickview' === Tools::getValue('action') - ? $tplHookPath . 'product-additional-info-quickview.tpl' - : $tplHookPath . 'product-additional-info.tpl'; + switch (Tools::getValue('action')) { + case 'quickview': + $filePath = $tplHookPath . 'product-additional-info-quickview.tpl'; + break; + case '': + $filePath = $tplHookPath . 'product-additional-info.tpl'; + break; + default: // 'refresh' and other unpredicted cases + $filePath = ''; + } } if (empty($variables) || empty($filePath)) { diff --git a/src/Entity/ProductCommentCriterion.php b/src/Entity/ProductCommentCriterion.php index b2421472..de610006 100644 --- a/src/Entity/ProductCommentCriterion.php +++ b/src/Entity/ProductCommentCriterion.php @@ -26,8 +26,8 @@ namespace PrestaShop\Module\ProductComment\Entity; +use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; -use Language; use Validate; /** @@ -67,34 +67,79 @@ class ProductCommentCriterion /** * @var array * - * Need to be implemented as ORM\OneToMany in the future + * @deprecated 6.0.3 - use criterionLangs instead */ private $names; + /** + * @ORM\OneToMany(targetEntity="PrestaShop\Module\ProductComment\Entity\ProductCommentCriterionLang", cascade={"persist", "remove"}, mappedBy="productcommentcriterion") + */ + private $criterionLangs; + /** * @var array * - * Need to be implemented as ORM\OneToMany in the future + * @todo implement as ORM\OneToMany in the future */ private $categories; /** * @var array * - * Need to be implemented as ORM\OneToMany in the future + * @todo implement as ORM\OneToMany in the future */ private $products; public function __construct() { - $langIsoIds = Language::getIsoIds(); - foreach ($langIsoIds as $langIsoId) { - $this->names[$langIsoId['id_lang']] = $langIsoId['iso_code']; + $this->criterionLangs = new ArrayCollection(); + } + + /** + * @return ArrayCollection + */ + public function getCriterionLangs() + { + return $this->criterionLangs; + } + + /** + * @return ProductCommentCriterionLang|null + */ + public function getCriterionLangByLangId(int $langId) + { + foreach ($this->criterionLangs as $criterionLang) { + if ($langId === $criterionLang->getLang()->getId()) { + return $criterionLang; + } + } + + return null; + } + + public function addCriterionLang(ProductCommentCriterionLang $criterionLang): self + { + $criterionLang->setProductCommentCriterion($this); + $this->criterionLangs->add($criterionLang); + + return $this; + } + + public function getCriterionName(): string + { + if ($this->criterionLangs->count() <= 0) { + return ''; } + + $criterionLang = $this->criterionLangs->first(); + + return $criterionLang->getName(); } /** * @return array + * + * @deprecated 6.0.3 - migrated to Form\ProductCommentCriterionFormDataProvider */ public function getNames() { @@ -105,6 +150,8 @@ public function getNames() * @param array $langNames * * @return ProductCommentCriterion + * + * @deprecated 6.0.3 */ public function setNames($langNames) { @@ -123,10 +170,8 @@ public function getCategories() /** * @param array $selectedCategories - * - * @return ProductCommentCriterion */ - public function setCategories($selectedCategories) + public function setCategories($selectedCategories): self { $this->categories = $selectedCategories; @@ -143,71 +188,47 @@ public function getProducts() /** * @param array $selectedProducts - * - * @return ProductCommentCriterion */ - public function setProducts($selectedProducts) + public function setProducts($selectedProducts): self { $this->products = $selectedProducts; return $this; } - /** - * @return int - */ - public function getId() + public function getId(): int { return $this->id; } - /** - * @return int - */ - public function getType() + public function getType(): int { return $this->type; } - /** - * @param int $type - * - * @return ProductCommentCriterion - */ - public function setType($type) + public function setType(int $type): self { $this->type = $type; return $this; } - /** - * @return bool - */ - public function isActive() + public function isActive(): bool { return $this->active; } - /** - * @param bool $active - * - * @return ProductCommentCriterion - */ - public function setActive($active) + public function setActive(bool $active): self { $this->active = $active; return $this; } - /** - * @return bool - */ - public function isValid() + public function isValid(): bool { - foreach ($this->names as $value) { - if (!Validate::isGenericName($value)) { + foreach ($this->criterionLangs as $criterionLang) { + if (!Validate::isGenericName($criterionLang->getName())) { return false; } } diff --git a/src/Entity/ProductCommentCriterionLang.php b/src/Entity/ProductCommentCriterionLang.php new file mode 100644 index 00000000..19373f7f --- /dev/null +++ b/src/Entity/ProductCommentCriterionLang.php @@ -0,0 +1,97 @@ +productcommentcriterion; + } + + public function setProductCommentCriterion(ProductCommentCriterion $productcommentcriterion): self + { + $this->productcommentcriterion = $productcommentcriterion; + + return $this; + } + + /** + * @return Lang + */ + public function getLang() + { + return $this->lang; + } + + /** + * @param Lang $lang + */ + public function setLang(Lang $lang): self + { + $this->lang = $lang; + + return $this; + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } +} diff --git a/src/Form/ProductCommentCriterionFormDataHandler.php b/src/Form/ProductCommentCriterionFormDataHandler.php new file mode 100644 index 00000000..8e0437d9 --- /dev/null +++ b/src/Form/ProductCommentCriterionFormDataHandler.php @@ -0,0 +1,121 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 + */ +declare(strict_types=1); + +namespace PrestaShop\Module\ProductComment\Form; + +use Doctrine\ORM\EntityManagerInterface; +use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterion; +use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterionLang; +use PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository; +use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataHandler\FormDataHandlerInterface; +use PrestaShopBundle\Entity\Repository\LangRepository; + +class ProductCommentCriterionFormDataHandler implements FormDataHandlerInterface +{ + /** + * @var ProductCommentCriterionRepository + */ + private $pccriterionRepository; + + /** + * @var LangRepository + */ + private $langRepository; + + /** + * @var EntityManagerInterface + */ + private $entityManager; + + /** + * @param ProductCommentCriterionRepository $pccriterionRepository + * @param LangRepository $langRepository + * @param EntityManagerInterface $entityManager + */ + public function __construct( + ProductCommentCriterionRepository $pccriterionRepository, + LangRepository $langRepository, + EntityManagerInterface $entityManager + ) { + $this->pccriterionRepository = $pccriterionRepository; + $this->langRepository = $langRepository; + $this->entityManager = $entityManager; + } + + /** + * {@inheritdoc} + */ + public function create(array $data) + { + } + + /** + * {@inheritdoc} + */ + public function update($id, array $data) + { + } + + /** + * @param ProductCommentCriterion $pccriterion + * @param array $pcc_languages + * + * @todo migrate this temporary function to above standard function create + */ + public function createLangs($pccriterion, $pcc_languages): void + { + foreach ($pcc_languages as $langId => $langContent) { + $lang = $this->langRepository->find($langId); + $pccriterionLang = new ProductCommentCriterionLang(); + $pccriterionLang + ->setLang($lang) + ->setName($langContent) + ; + $pccriterion->addCriterionLang($pccriterionLang); + } + + $this->entityManager->persist($pccriterion); + $this->entityManager->flush(); + } + + /** + * @param ProductCommentCriterion $pccriterion + * @param array $pcc_languages + * + * @todo migrate this temporary function to above standard function update + */ + public function updateLangs($pccriterion, $pcc_languages): void + { + foreach ($pcc_languages as $langId => $langContent) { + $lang = $this->langRepository->find($langId); + $pccriterionLang = $pccriterion->getCriterionLangByLangId($langId); + if (null === $pccriterionLang) { + continue; + } + $pccriterionLang + ->setName($langContent) + ; + } + + $this->entityManager->persist($pccriterion); + $this->entityManager->flush(); + } +} diff --git a/src/Form/ProductCommentCriterionFormDataProvider.php b/src/Form/ProductCommentCriterionFormDataProvider.php new file mode 100644 index 00000000..9b8397d9 --- /dev/null +++ b/src/Form/ProductCommentCriterionFormDataProvider.php @@ -0,0 +1,88 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 + */ +declare(strict_types=1); + +namespace PrestaShop\Module\ProductComment\Form; + +use PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository; +use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\DataProvider\FormDataProviderInterface; +use PrestaShopBundle\Entity\Repository\LangRepository; + +class ProductCommentCriterionFormDataProvider implements FormDataProviderInterface +{ + /** + * @var ProductCommentCriterionRepository + */ + private $pccriterionRepository; + + /** + * @var LangRepository + */ + private $langRepository; + + /** + * @param ProductCommentCriterionRepository $pccriterionRepository + * @param LangRepository $langRepository + */ + public function __construct( + ProductCommentCriterionRepository $pccriterionRepository, + LangRepository $langRepository + ) { + $this->pccriterionRepository = $pccriterionRepository; + $this->langRepository = $langRepository; + } + + /** + * {@inheritdoc} + */ + public function getData($criterionId) + { + $criterion = $this->pccriterionRepository->find($criterionId); + + $criterionData = [ + 'type' => $criterion->getType(), + 'active' => $criterion->isActive(), + ]; + foreach ($criterion->getCriterionLangs() as $criterionLang) { + $criterionData['name'][$criterionLang->getLang()->getId()] = $criterionLang->getName(); + } + + return $criterionData; + } + + /** + * {@inheritdoc} + */ + public function getDefaultData() + { + $default_name = []; + + $langEntities = $this->langRepository->findBy(['active' => 1]); + foreach ($langEntities as $langEntity) { + $default_name[$langEntity->getId()] = $langEntity->getIsoCode(); + } + + return [ + 'type' => '', + 'active' => false, + 'name' => $default_name, + ]; + } +} diff --git a/src/Form/index.php b/src/Form/index.php new file mode 100644 index 00000000..45df26c5 --- /dev/null +++ b/src/Form/index.php @@ -0,0 +1,34 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) + */ +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); + +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + +header('Location: ../'); +exit; diff --git a/src/Repository/ProductCommentCriterionRepository.php b/src/Repository/ProductCommentCriterionRepository.php index 7446f671..c978e5b4 100644 --- a/src/Repository/ProductCommentCriterionRepository.php +++ b/src/Repository/ProductCommentCriterionRepository.php @@ -88,6 +88,9 @@ public function remove(ProductCommentCriterion $entity, bool $flush = false): vo } } + /** + * @deprecated 6.0.3 - cascade remove by Entity setting instead + */ private function deleteLangs($criterion): int { return $this->connection->executeUpdate(' @@ -112,33 +115,34 @@ private function deleteProducts($criterion): int private function deleteGrades($criterion): int { return $this->connection->executeUpdate(' - DELETE FROM `' . _DB_PREFIX_ . 'product_comment_criterion_grade` + DELETE FROM `' . _DB_PREFIX_ . 'product_comment_grade` WHERE `id_product_comment_criterion` = ' . $criterion->getId()); } - /* Remove a criterion and Delete its manual relation _lang, _category, _product, _grade */ + /* Remove a criterion and Delete its manual relation _category, _product, _grade */ public function delete(ProductCommentCriterion $criterion): int { $res = 0; $criterionType = $criterion->getType(); - $this->remove($criterion, true); - - $res += $this->deleteLangs($criterion); - if ($criterionType == ProductCommentCriterion::CATEGORIES_TYPE) { $res += $this->deleteCategories($criterion); } elseif ($criterionType == ProductCommentCriterion::PRODUCTS_TYPE) { $res += $this->deleteProducts($criterion); + } else { + $res = 1; } $res += $this->deleteGrades($criterion); + $this->remove($criterion, true); + + // todo: return void, and use try catch Exception instead return $res; } - /* Update a criterion and Update its manual relation _lang, _category, _product, _grade */ + /* Update a criterion and Update its manual relation _category, _product */ public function update(ProductCommentCriterion $criterion): int { $res = 0; @@ -148,20 +152,23 @@ public function update(ProductCommentCriterion $criterion): int $this->getEntityManager()->persist($criterion); $this->getEntityManager()->flush(); - $res += $this->deleteLangs($criterion); - $res += $this->updateLangs($criterion); - if ($criterionType == ProductCommentCriterion::CATEGORIES_TYPE) { $res += $this->deleteCategories($criterion); $res += $this->updateCategories($criterion); } elseif ($criterionType == ProductCommentCriterion::PRODUCTS_TYPE) { $res += $this->deleteProducts($criterion); $res += $this->updateProducts($criterion); + } else { + $res = 1; } + // todo: return void, and use try catch Exception instead return $res; } + /** + * @deprecated 6.0.3 - migrated to Form\ProductCommentCriterionFormDataHandler + */ private function updateLangs($criterion): int { $res = 0; @@ -217,15 +224,18 @@ private function updateProducts($criterion): int return $res; } + public function updateGeneral(ProductCommentCriterion $criterion): void + { + $this->getEntityManager()->persist($criterion); + $this->getEntityManager()->flush(); + } + /** - * @param int $idProduct - * @param int $idLang - * * @return array * * @throws \PrestaShopException */ - public function getByProduct($idProduct, $idLang) + public function getByProduct(int $idProduct, int $idLang) { /** @var QueryBuilder $qb */ $qb = $this->connection->createQueryBuilder(); @@ -255,11 +265,9 @@ public function getByProduct($idProduct, $idLang) } /** - * Get Criterions - * * @return array Criterions */ - public function getCriterions($id_lang, $type = false, $active = false) + public function getCriterions(int $id_lang, $type = false, $active = false) { $sql = ' SELECT pcc.`id_product_comment_criterion`, pcc.id_product_comment_criterion_type, pccl.`name`, pcc.active @@ -278,8 +286,6 @@ public function getCriterions($id_lang, $type = false, $active = false) } /** - * @param int $id_criterion - * * @return array */ public function getProducts(int $id_criterion) @@ -302,8 +308,6 @@ public function getProducts(int $id_criterion) } /** - * @param int $id_criterion - * * @return array */ public function getCategories(int $id_criterion) @@ -340,25 +344,14 @@ public function getTypes() } /** - * Get Criterion with names in active languages - * * @return ProductCommentCriterion + * + * @deprecated 6.0.3 - use standard find() instead */ 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(); } diff --git a/tests/phpstan.sh b/tests/phpstan.sh index 9fcc0c62..c86154ff 100755 --- a/tests/phpstan.sh +++ b/tests/phpstan.sh @@ -14,7 +14,7 @@ docker run -tid --rm -v ps-volume:/var/www/html --name temp-ps prestashop/presta # Clear previous instance of the module in the PrestaShop volume echo "Clear previous module" -docker exec -t temp-ps rm -rf /var/www/html/modules/productcomments +docker exec -t --user root temp-ps sh -c 'find /var/www/html/modules/productcomments -type f -exec rm {} +' # Run a container for PHPStan, having access to the module content and PrestaShop sources. # This tool is outside the composer.json because of the compatibility with PHP 5.6 diff --git a/upgrade/install-2.4.php b/upgrade/install-2.4.0.php similarity index 96% rename from upgrade/install-2.4.php rename to upgrade/install-2.4.0.php index da9bae79..af6d0a32 100644 --- a/upgrade/install-2.4.php +++ b/upgrade/install-2.4.0.php @@ -27,7 +27,7 @@ exit; } -function upgrade_module_2_4($object) +function upgrade_module_2_4_0($object) { return $object->registerHook('displayProductListReviews') && $object->registerHook('top'); } diff --git a/upgrade/install-6.0.3.php b/upgrade/install-6.0.3.php new file mode 100644 index 00000000..b32ad47c --- /dev/null +++ b/upgrade/install-6.0.3.php @@ -0,0 +1,40 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) + */ +if (!defined('_PS_VERSION_')) { + exit; +} + +function upgrade_module_6_0_3($object) +{ + return Db::getInstance()->execute('ALTER TABLE `' . _DB_PREFIX_ . 'product_comment` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci') + && Db::getInstance()->execute('ALTER TABLE `' . _DB_PREFIX_ . 'product_comment_criterion` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci') + && Db::getInstance()->execute('ALTER TABLE `' . _DB_PREFIX_ . 'product_comment_criterion_product` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci') + && Db::getInstance()->execute('ALTER TABLE `' . _DB_PREFIX_ . 'product_comment_criterion_lang` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci') + && Db::getInstance()->execute('ALTER TABLE `' . _DB_PREFIX_ . 'product_comment_criterion_category` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci') + && Db::getInstance()->execute('ALTER TABLE `' . _DB_PREFIX_ . 'product_comment_grade` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci') + && Db::getInstance()->execute('ALTER TABLE `' . _DB_PREFIX_ . 'product_comment_usefulness` CHARACTER SET = utf8mb4 COLLATE utf8mb4_general_ci') + && Db::getInstance()->execute('ALTER TABLE `' . _DB_PREFIX_ . 'product_comment_report` CHARACTER SET = utf8mb4 COLLATE utf8mb4_general_ci'); +} diff --git a/views/css/productcomments.css b/views/css/productcomments.css index 106d2808..d87f2dbe 100644 --- a/views/css/productcomments.css +++ b/views/css/productcomments.css @@ -291,6 +291,12 @@ font-weight: bold; } +#ratingNotChosen { + font-size: smaller; + color: #ab4746; + text-align: right; +} + #post-product-comment-form input.error, #post-product-comment-form textarea.error { background-color: #f2dede; diff --git a/views/js/jquery.rating.plugin.js b/views/js/jquery.rating.plugin.js index b466e9fd..755dbdbc 100644 --- a/views/js/jquery.rating.plugin.js +++ b/views/js/jquery.rating.plugin.js @@ -96,6 +96,7 @@ jQuery.fn.rating = function(generalOptions) { newStar.on('click', function selectGrade() { var selectedGrade = $(this).data('grade'); ratingInput.val(selectedGrade); + ratingChosen = true; }); fullStars.append(newStar); } diff --git a/views/js/list-comments.js b/views/js/list-comments.js index 89bc6c40..06de9d5c 100644 --- a/views/js/list-comments.js +++ b/views/js/list-comments.js @@ -180,9 +180,18 @@ jQuery(document).ready(function () { commentsList.append($comment); } - function updateCommentUsefulness($comment, commentId, usefulness) { - $.post(updateCommentUsefulnessUrl, {id_product_comment: commentId, usefulness: usefulness}, function(jsonData){ - if (jsonData) { + async function updateCommentUsefulness($comment, commentId, usefulness) { + try { + const response = await fetch(updateCommentUsefulnessUrl, { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + body: "id_product_comment=" + commentId + "&usefulness=" + usefulness, + }); + + if (response.status === 200) { + const jsonData = await response.json(); if (jsonData.success) { $('.useful-review-value', $comment).html(jsonData.usefulness); $('.not-useful-review-value', $comment).html(jsonData.total_usefulness - jsonData.usefulness); @@ -193,9 +202,9 @@ jQuery(document).ready(function () { } else { showUpdatePostCommentErrorModal(productCommentUpdatePostErrorMessage); } - }).fail(function() { - showUpdatePostCommentErrorModal(productCommentUpdatePostErrorMessage); - }); + } catch (error) { + showUpdatePostCommentErrorModal(error); + } } function confirmCommentAbuse(commentId) { @@ -204,20 +213,33 @@ jQuery(document).ready(function () { if (!confirm) { return; } - $.post(reportCommentUrl, {id_product_comment: commentId}, function(jsonData){ - if (jsonData) { - if (jsonData.success) { - reportCommentPostedModal.modal('show'); - } else { - showReportCommentErrorModal(jsonData.error); - } + confirmCommentAbuseFetch(commentId); + }) + } + + async function confirmCommentAbuseFetch(commentId) { + try { + const response = await fetch(reportCommentUrl, { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + body: "id_product_comment=" + commentId, + }); + + if (response.status === 200) { + const jsonData = await response.json(); + if (jsonData.success) { + reportCommentPostedModal.modal('show'); } else { - showReportCommentErrorModal(productCommentAbuseReportErrorMessage); + showReportCommentErrorModal(jsonData.error); } - }).fail(function() { + } else { showReportCommentErrorModal(productCommentAbuseReportErrorMessage); - }); - }) + } + } catch (error) { + showReportCommentErrorModal(error); + } } if (totalPages <= 1) diff --git a/views/js/post-comment.js b/views/js/post-comment.js index 3601f882..cf593b54 100644 --- a/views/js/post-comment.js +++ b/views/js/post-comment.js @@ -39,10 +39,16 @@ jQuery(document).ready(function () { const commentPostedModal = $('#product-comment-posted-modal'); const commentPostErrorModal = $('#product-comment-post-error'); + const criterionsList = $('#criterions_list'); + criterionsList.append('
* ' + productCommentMandatoryMessage + '
'); + const criterionsInfo = $('#ratingNotChosen'); + function showPostCommentModal() { commentPostedModal.modal('hide'); commentPostErrorModal.modal('hide'); postCommentModal.modal('show'); + ratingChosen = false; + criterionsInfo.hide(); } function showCommentPostedModal() { @@ -122,7 +128,14 @@ jQuery(document).ready(function () { $(fieldSelector).removeClass('error'); $(fieldSelector).addClass('valid'); } - }); + + if (!ratingChosen) { + criterionsInfo.show(); + isValid = false; + } else { + criterionsInfo.hide(); + } + }); return isValid; } diff --git a/views/js/productListingComments.js b/views/js/productListingComments.js index c384f755..2c21269b 100644 --- a/views/js/productListingComments.js +++ b/views/js/productListingComments.js @@ -43,7 +43,7 @@ var productListingComments = (function () { productListReviewsContainer: '.product-list-reviews', productListReviewsNumberOfComments: '.comments-nb', productListReviewsStarsContainer: '.grade-stars', - productContainer: '.thumbnail-container' + productContainer: '.js-product-miniature' }; var DOMClasses = { diff --git a/views/templates/hook/post-comment-modal.tpl b/views/templates/hook/post-comment-modal.tpl index 81a75659..4c682ace 100644 --- a/views/templates/hook/post-comment-modal.tpl +++ b/views/templates/hook/post-comment-modal.tpl @@ -25,6 +25,8 @@