From 080b08ca7b1445f016322d4a4b15eb7615b9f443 Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:01:16 -0600
Subject: [PATCH 01/28] adds ProductComment hook
---
src/Hook/ProductComment.php | 70 +++++++++++++++++++++++++++++++++++++
src/HookDispatcher.php | 1 +
2 files changed, 71 insertions(+)
create mode 100755 src/Hook/ProductComment.php
diff --git a/src/Hook/ProductComment.php b/src/Hook/ProductComment.php
new file mode 100755
index 000000000..9c01c30d6
--- /dev/null
+++ b/src/Hook/ProductComment.php
@@ -0,0 +1,70 @@
+
+ * @copyright Since 2007 PrestaShop SA and Contributors
+ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
+ */
+
+namespace PrestaShop\Module\FacetedSearch\Hook;
+
+class ProductComment extends AbstractHook
+{
+ const AVAILABLE_HOOKS = [
+ 'actionObjectProductCommentValidateAfter',
+ ];
+
+ /**
+ * Product Comment Validate After
+ *
+ * Smart index after validating a comment
+ *
+ * @param array $params
+ */
+ public function actionObjectProductCommentValidateAfter(array $params)
+ {
+ $grade = $params['object'];
+
+ $commentLogRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index_log`
+ WHERE id_comment = ' . $grade->id . ' AND indexed = 1');
+
+ if (empty($commentLogRow)){
+ $gradeCommentRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index`
+ WHERE id_product =' . $grade->id_product);
+
+ if (empty($gradeCommentRow) || !$gradeCommentRow){
+ //insert the first index record for this comment
+ $this->database->execute('INSERT INTO `'._DB_PREFIX_.'layered_comment_index` (`id_product`, `score`, `avg_score`) VALUES ('.$grade->id_product.', '.$grade->grade.','.$grade->grade.')');
+
+ $this->addCommentIndexLog($grade);
+ }else{
+ //update index for the comment
+ $productCommentLogRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index_log`
+ WHERE id_product = ' . $grade->id_product . ' AND indexed = 1');
+
+ $newGradeValue = (int)$gradeCommentRow[0]['score'] + (int)$grade->grade;
+ $avg_score = $newGradeValue/(count($productCommentLogRow)+1);
+
+ $this->database->execute('update ' . _DB_PREFIX_ . 'layered_comment_index set score='.$newGradeValue.', avg_score= '.$avg_score .' where id_product=' . $grade->id_product);
+
+ $this->addCommentIndexLog($grade);
+ }
+ }
+ }
+
+ public function addCommentIndexLog($comment){
+ $this->database->execute('INSERT INTO `'._DB_PREFIX_.'layered_comment_index_log` (`id_comment`, `indexed`, `id_product`) VALUES ('.$comment->id.', 1,'. $comment->id_product .')');
+ }
+}
diff --git a/src/HookDispatcher.php b/src/HookDispatcher.php
index 459334245..35805c053 100644
--- a/src/HookDispatcher.php
+++ b/src/HookDispatcher.php
@@ -40,6 +40,7 @@ class HookDispatcher
Hook\Product::class,
Hook\ProductSearch::class,
Hook\SpecificPrice::class,
+ Hook\ProductComment::class,
];
/**
From a029235f3b03d53ae14ff07c1edb552b01cb8a4a Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:15:32 -0600
Subject: [PATCH 02/28] methods to index reviews
---
ps_facetedsearch.php | 90 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 89 insertions(+), 1 deletion(-)
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index 5029e7bf9..4df9fb7c7 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -165,6 +165,10 @@ protected function getDefaultFilters()
'label' => 'Product price filter (slider)',
'slider' => true,
],
+ 'layered_selection_review_star' => [
+ 'label' => 'Avg. Customer Review',
+ 'star' => true
+ ],
];
}
@@ -213,6 +217,8 @@ public function install()
$this->rebuildPriceIndexTable();
$this->installIndexableAttributeTable();
$this->installProductAttributeTable();
+ $this->rebuildCommentIndexTable();
+ $this->indexReviews(true);
if ($productsCount < static::LOCK_TOO_MANY_PRODUCTS) {
$this->fullPricesIndexProcess();
@@ -880,7 +886,7 @@ public function rebuildLayeredStructure()
`id_shop` INT(11) UNSIGNED NOT NULL,
`id_category` INT(10) UNSIGNED NOT NULL,
`id_value` INT(10) UNSIGNED NULL DEFAULT \'0\',
- `type` ENUM(\'category\',\'id_feature\',\'id_attribute_group\',\'quantity\',\'condition\',\'manufacturer\',\'weight\',\'price\') NOT NULL,
+ `type` ENUM(\'category\',\'id_feature\',\'id_attribute_group\',\'quantity\',\'condition\',\'manufacturer\',\'weight\',\'price\',\'review\') NOT NULL,
`position` INT(10) UNSIGNED NOT NULL,
`filter_type` int(10) UNSIGNED NOT NULL DEFAULT 0,
`filter_show_limit` int(10) UNSIGNED NOT NULL DEFAULT 0,
@@ -1162,6 +1168,8 @@ public function buildLayeredCategories()
} elseif (substr($key, 0, 23) == 'layered_selection_feat_') {
$sqlInsert .= '(' . (int) $idCategory . ', ' . (int) $idShop . ', ' . (int) str_replace('layered_selection_feat_', '', $key) . ',
\'id_feature\',' . (int) $n . ', ' . (int) $limit . ', ' . (int) $type . '),';
+ } elseif ($key == 'layered_selection_review_star') {
+ $sqlInsert .= '(' . (int) $idCategory . ', ' . (int) $idShop . ', NULL,\'review\',' . (int) $n . ', ' . (int) $limit . ', ' . (int) $type . '),';
}
++$nbSqlValuesToInsert;
@@ -1503,4 +1511,84 @@ public function getWidgetVariables($hookName, array $configuration)
{
return [];
}
+
+ /**
+ * Install review indexes table
+ */
+ public function rebuildCommentIndexTable()
+ {
+ $this->getDatabase()->execute('DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'layered_comment_index`');
+
+ $this->getDatabase()->execute('DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'layered_comment_index_log`');
+
+ $this->getDatabase()->execute(
+ 'CREATE TABLE `' . _DB_PREFIX_ . 'layered_comment_index` (
+ `id_product` INT NOT NULL,
+ `score` INT NOT NULL,
+ `avg_score` FLOAT NOT NULL,
+ PRIMARY KEY (`id_product`),
+ INDEX `score` (`score`),
+ INDEX `avg_score` (`score`)
+ ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;'
+ );
+
+ $this->getDatabase()->execute(
+ 'CREATE TABLE `' . _DB_PREFIX_ . 'layered_comment_index_log` (
+ `id_comment` INT NOT NULL,
+ `id_product` INT NOT NULL,
+ `indexed` TINYINT(1) NOT NULL,
+ PRIMARY KEY (`id_comment`)
+ ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;'
+ );
+ }
+
+ public function indexReviews($full = false)
+ {
+ if ($full) {
+ $query = 'SELECT avg(`grade`) as avg_grade, sum(`grade`) as sum_grade, `id_product` FROM ' . _DB_PREFIX_ . 'product_comment
+group by id_product';
+
+ foreach ($this->getDatabase()->executeS($query) as $comment) {
+ $this->addCommentIndex($comment);
+ }
+
+ $query = 'SELECT `id_product_comment`, `id_product` FROM ' . _DB_PREFIX_ . 'product_comment';
+
+ foreach ($this->getDatabase()->executeS($query) as $commentLog) {
+ $this->addCommentIndexLog($commentLog);
+ }
+
+ } else {
+ $query = 'select pc.id_product_comment, pc.id_product, pc.grade from ps_product_comment as pc
+left join ps_layered_comment_index_log as lc
+on pc.id_product_comment = lc.id_comment
+where lc.indexed is null;';
+
+ //returns non matching records
+ foreach ($this->getDatabase()->executeS($query) as $commentLog) {
+ $gradeCommentRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index`
+ WHERE id_product =' . $commentLog['id_product']);
+
+ $productCommentLogRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index_log`
+ WHERE id_product = ' . $commentLog['id_product'] . ' AND indexed = 1');
+
+ $newGradeValue = (int)$gradeCommentRow[0]['score'] + (int)$commentLog['grade'];
+ $avg_score = $newGradeValue/(count($productCommentLogRow)+1);
+
+ $this->database->execute('update ' . _DB_PREFIX_ . 'layered_comment_index set score='.$newGradeValue.', avg_score= '.$avg_score .' where id_product=' . $commentLog['id_product']);
+
+ $this->addCommentIndexLog($commentLog);
+ }
+ }
+
+ return "true";
+ }
+
+ public function addCommentIndex($comment){
+ $this->database->execute('INSERT INTO `'._DB_PREFIX_.'layered_comment_index` (`id_product`, `score`, `avg_score`) VALUES ('.$comment['id_product'].', '.$comment['sum_grade'].','.$comment['avg_grade'].')');
+ }
+
+ public function addCommentIndexLog($commentLog){
+ $this->database->execute('INSERT INTO `'._DB_PREFIX_.'layered_comment_index_log` (`id_comment`, `indexed`, `id_product`) VALUES ('.$commentLog['id_product_comment'].', 1,'. $commentLog['id_product'] .')');
+ }
}
From 9666de21427ebeb5e8c155a89b73215455d8faa7 Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:21:03 -0600
Subject: [PATCH 03/28] admin items
---
views/templates/admin/view.tpl | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/views/templates/admin/view.tpl b/views/templates/admin/view.tpl
index 54ad7a6cd..af4f5a15c 100644
--- a/views/templates/admin/view.tpl
+++ b/views/templates/admin/view.tpl
@@ -69,6 +69,8 @@
{l s='Filter style:' d='Modules.Facetedsearch.Admin'}
{if !empty($filter['slider'])}
{l s='List of ranges' d='Modules.Facetedsearch.Admin'}
+ {elseif !empty($filter['star'])}
+ {l s='List of stars' d='Modules.Facetedsearch.Admin'}
{else}
@@ -80,7 +82,7 @@
{/if}
- {if empty($filter['slider'])}
+ {if empty($filter['slider']) && empty($filter['star'])}
{l s='Filter result limit:' d='Modules.Facetedsearch.Admin'}
{call get_limit_select element=$filterId}
From 8f2f4f7b91cc5ec72529fee6da0c3e19e927a3bd Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:26:15 -0600
Subject: [PATCH 04/28] admin add filter view
---
views/templates/admin/add.tpl | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
mode change 100644 => 100755 views/templates/admin/add.tpl
diff --git a/views/templates/admin/add.tpl b/views/templates/admin/add.tpl
old mode 100644
new mode 100755
index 77d3d2f96..9b90a4fe4
--- a/views/templates/admin/add.tpl
+++ b/views/templates/admin/add.tpl
@@ -220,6 +220,30 @@
+
+
+
+ {l s='Avg. Customer Reviews' d='Modules.Facetedsearch.Admin'}
+
+
+
+
+
{l s='Filter style:' d='Modules.Facetedsearch.Admin'}
+
+
+
{l s='List of ranges' d='Modules.Facetedsearch.Admin'}
+
+
+
{if $attribute_groups|count > 0}
{foreach $attribute_groups as $attribute_group}
From f9f96a682f66f934e36f46953eb3325cc96b3682 Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:32:50 -0600
Subject: [PATCH 05/28] adds review block
---
src/Filters/Block.php | 68 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/src/Filters/Block.php b/src/Filters/Block.php
index fe582b66a..8889e1891 100644
--- a/src/Filters/Block.php
+++ b/src/Filters/Block.php
@@ -115,6 +115,9 @@ public function getFilterBlock(
case 'price':
$filterBlocks[] = $this->getPriceRangeBlock($filter, $selectedFilters, $nbProducts);
break;
+ case 'review':
+ $filterBlocks[] = $this->getReviweBlock($filter, $selectedFilters);
+ break;
case 'weight':
$filterBlocks[] = $this->getWeightRangeBlock($filter, $selectedFilters, $nbProducts);
break;
@@ -979,4 +982,69 @@ private function preparePriceSpecifications()
'currencySymbol' => $currency->sign,
];
}
+
+ /**
+ * Get the reviews filter block
+ *
+ * @param array $filter
+ * @param array $selectedFilters
+ *
+ * @return array
+ */
+ private function getReviweBlock($filter, $selectedFilters)
+ {
+ $values = [
+ '4' => ['name'=>"4"],
+ '3' => ['name'=>"3"],
+ '2' => ['name'=>"2"],
+ '1' => ['name'=>"1"],
+ ];
+
+ $query = 'SELECT count(g.grade) as count ,g.grade FROM (SELECT t.id_product, case
+when t.avg_grade between 1 and 1.99 then "1"
+when t.avg_grade between 2 and 2.99 then "2"
+when t.avg_grade between 3 and 3.99 then "3"
+when t.avg_grade between 4 and 5 then "4"
+end as grade
+ FROM (SELECT avg(h.grade) as avg_grade,
+ h.id_product FROM
+ (select pc.id_product, pc.grade from ' . _DB_PREFIX_ . 'product_comment as pc
+inner join (SELECT * FROM ' . _DB_PREFIX_ . 'category_product where id_category = '.$_GET['id_category'].') cp
+on pc.id_product = cp.id_product) h
+group by id_product) t) g
+group by g.grade
+order by g.grade ASC';
+ $gradeCounts = $this->database->executeS($query);
+
+ if (!empty($gradeCounts)){
+ foreach ($values as $value){
+ $nbr = 0;
+ foreach ($gradeCounts as $count){
+ if ((int)$value['name'] <= $count['grade']){
+ $nbr += $count['count'];
+ }
+ }
+ $values[$value['name']]['nbr'] = $nbr;
+ }
+ }
+
+ if (isset($selectedFilters['review'])){
+ $reviewValues = $selectedFilters['review'];
+ foreach ($reviewValues as $rv){
+ $values[$rv]['checked'] = true;
+ }
+ }
+
+ $reviewBlock = [
+ 'type_lite' => 'review',
+ 'type' => 'review',
+ 'id_key' => 0,
+ 'name' => $this->context->getTranslator()->trans('Avg. Customer Reviews', [], 'Modules.Facetedsearch.Shop'),
+ 'values' => $values,
+ 'filter_show_limit' => (int) $filter['filter_show_limit'],
+ 'filter_type' => Converter::WIDGET_TYPE_STAR,
+ ];
+
+ return $reviewBlock;
+ }
}
From 1c99bff2a4d08efca70814f6f7f6c6a1eeda4328 Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:34:52 -0600
Subject: [PATCH 06/28] adds review type to converter
---
src/Filters/Converter.php | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/src/Filters/Converter.php b/src/Filters/Converter.php
index 45a35d31d..15ffb4f12 100644
--- a/src/Filters/Converter.php
+++ b/src/Filters/Converter.php
@@ -38,6 +38,7 @@ class Converter
const WIDGET_TYPE_RADIO = 1;
const WIDGET_TYPE_DROPDOWN = 2;
const WIDGET_TYPE_SLIDER = 3;
+ const WIDGET_TYPE_STAR = 4;
const TYPE_ATTRIBUTE_GROUP = 'id_attribute_group';
const TYPE_AVAILABILITY = 'availability';
@@ -48,6 +49,7 @@ class Converter
const TYPE_MANUFACTURER = 'manufacturer';
const TYPE_PRICE = 'price';
const TYPE_WEIGHT = 'weight';
+ const TYPE_REVIEW = 'review';
const PROPERTY_URL_NAME = 'url_name';
const PROPERTY_COLOR = 'color';
@@ -195,6 +197,34 @@ public function getFacetsFromFilterBlocks(array $filterBlocks)
$facet->addFilter($filter);
+ break;
+ case self::TYPE_REVIEW:
+ $type = $filterBlock['type'];
+
+ $facet
+ ->setType($type)
+ ->setMultipleSelectionAllowed(false);
+
+ $filters = [];
+ foreach ($filterBlock['values'] as $id => $filterArray) {
+ $filter = new Filter();
+ $filter
+ ->setType($type)
+ ->setLabel($filterArray['name'])
+ ->setMagnitude($filterArray['nbr'])
+ ->setValue($id);
+
+ if (array_key_exists('checked', $filterArray)) {
+ $filter->setActive($filterArray['checked']);
+ }
+
+ $filters[] = $filter;
+ }
+
+ foreach ($filters as $filter) {
+ $facet->addFilter($filter);
+ }
+
break;
}
@@ -215,6 +245,10 @@ public function getFacetsFromFilterBlocks(array $filterBlocks)
$facet->setMultipleSelectionAllowed(false);
$facet->setWidgetType('slider');
break;
+ case self::WIDGET_TYPE_STAR:
+ $facet->setMultipleSelectionAllowed(false);
+ $facet->setWidgetType('star');
+ break;
}
$facets[] = $facet;
@@ -438,6 +472,8 @@ public function createFacetedSearchFiltersFromQuery(ProductSearchQuery $query)
private function convertFilterTypeToLabel($filterType)
{
switch ($filterType) {
+ case self::TYPE_REVIEW:
+ return $this->context->getTranslator()->trans('Avg. Customer Reviews', [], 'Modules.Facetedsearch.Shop');
case self::TYPE_PRICE:
return $this->context->getTranslator()->trans('Price', [], 'Modules.Facetedsearch.Shop');
case self::TYPE_WEIGHT:
From d50e526c949d6a87a1233b28090052a2b3fff23e Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:36:38 -0600
Subject: [PATCH 07/28] adds review sort
---
src/Product/SearchProvider.php | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/Product/SearchProvider.php b/src/Product/SearchProvider.php
index 54366f921..1778e8111 100644
--- a/src/Product/SearchProvider.php
+++ b/src/Product/SearchProvider.php
@@ -86,6 +86,7 @@ private function getAvailableSortOrders()
$sortNameDesc = new SortOrder('product', 'name', 'desc');
$sortPriceAsc = new SortOrder('product', 'price', 'asc');
$sortPriceDesc = new SortOrder('product', 'price', 'desc');
+ $sortBestRated = new SortOrder('product', 'avg_score', 'desc');
$translator = $this->module->getTranslator();
return [
@@ -107,6 +108,9 @@ private function getAvailableSortOrders()
$sortPriceDesc->setLabel(
$translator->trans('Price, high to low', [], 'Shop.Theme.Catalog')
),
+ $sortBestRated->setLabel(
+ $translator->trans('Sort Best Rated', [], 'Shop.Theme.Catalog')
+ ),
];
}
From a4b11d7e8136734c2f0b97a5333a572b37a570f9 Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:40:37 -0600
Subject: [PATCH 08/28] updates css and js
---
views/dist/front.css | 4 ++--
views/dist/front.js | 17 ++++++++++++++++-
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/views/dist/front.css b/views/dist/front.css
index 0746a873e..3275ad6ba 100644
--- a/views/dist/front.css
+++ b/views/dist/front.css
@@ -2,7 +2,7 @@
#search_filters .ui-slider-horizontal .ui-slider-handle{margin-left:-1px;cursor:pointer}#search_filters .ui-widget-header{background:#555}#search_filters .ui-slider .ui-slider-handle{top:-.45em;width:0.4em;background:#fff;border:1px solid #555}#search_filters .ui-slider-horizontal{height:.4em}
-#search_filters .facet .title{display:flex}#search_filters .facet .title .collapse-icons{margin-left:auto}#search_filters .facet .facet-title{width:calc(100% - 30px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#search_filters .facet .facet-label{width:100%;text-align:left}#search_filters .facet .facet-label .custom-checkbox,#search_filters .facet .facet-label .custom-radio{top:-7px;margin-right:0}#search_filters .facet .facet-label .color{margin-left:0}#search_filters .facet .facet-label a{width:calc(100% - 30px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
+#search_filters .facet .title{display:flex}#search_filters .facet .title .collapse-icons{margin-left:auto}#search_filters .facet .facet-title{width:calc(100% - 30px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#search_filters .facet .facet-label{width:100%;text-align:left}#search_filters .facet .facet-label .custom-checkbox,#search_filters .facet .facet-label .custom-radio{top:-7px;margin-right:0}#search_filters .facet .facet-label .color{margin-left:0}#search_filters .facet .facet-label a{width:calc(100% - 30px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap} #search_filters .facet .facet-label a.star-link{width: 100%}
-/*# sourceMappingURL=front.css.map*/
\ No newline at end of file
+/*# sourceMappingURL=front.css.map*/
diff --git a/views/dist/front.js b/views/dist/front.js
index 64d4ffc3b..2db5e4945 100644
--- a/views/dist/front.js
+++ b/views/dist/front.js
@@ -1,3 +1,18 @@
/*! For license information please see front.js.LICENSE.txt */
(()=>{var t={557:()=>{!function(t){if(t.support.touch="ontouchend"in document,t.support.touch){var e,n=t.ui.mouse.prototype,r=n._mouseInit,i=n._mouseDestroy;n._touchStart=function(t){!e&&this._mouseCapture(t.originalEvent.changedTouches[0])&&(e=!0,this._touchMoved=!1,o(t,"mouseover"),o(t,"mousemove"),o(t,"mousedown"))},n._touchMove=function(t){e&&(this._touchMoved=!0,o(t,"mousemove"))},n._touchEnd=function(t){e&&(o(t,"mouseup"),o(t,"mouseout"),this._touchMoved||o(t,"click"),e=!1)},n._mouseInit=function(){var e=this;e.element.bind({touchstart:t.proxy(e,"_touchStart"),touchmove:t.proxy(e,"_touchMove"),touchend:t.proxy(e,"_touchEnd")}),r.call(e)},n._mouseDestroy=function(){var e=this;e.element.unbind({touchstart:t.proxy(e,"_touchStart"),touchmove:t.proxy(e,"_touchMove"),touchend:t.proxy(e,"_touchEnd")}),i.call(e)}}function o(t,e){if(!(t.originalEvent.touches.length>1)){t.preventDefault();var n=t.originalEvent.changedTouches[0],r=document.createEvent("MouseEvents");r.initMouseEvent(e,!0,!0,window,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),t.target.dispatchEvent(r)}}}(jQuery)},658:(t,e,n)=>{var r=/[\\^$.*+?()[\]{}|]/g,i=RegExp(r.source),o="object"==typeof n.g&&n.g&&n.g.Object===Object&&n.g,a="object"==typeof self&&self&&self.Object===Object&&self,u=o||a||Function("return this")(),c=Object.prototype.toString,s=u.Symbol,l=s?s.prototype:void 0,f=l?l.toString:void 0;t.exports=function(t){var e;return(t=null==(e=t)?"":function(t){if("string"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return!!t&&"object"==typeof t}(t)&&"[object Symbol]"==c.call(t)}(t))return f?f.call(t):"";var e=t+"";return"0"==e&&1/t==-1/0?"-0":e}(e))&&i.test(t)?t.replace(r,"\\$&"):t}},741:()=>{},580:()=>{},765:()=>{},379:(t,e,n)=>{"use strict";var r,i=function(){var t={};return function(e){if(void 0===t[e]){var n=document.querySelector(e);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(t){n=null}t[e]=n}return t[e]}}(),o=[];function a(t){for(var e=-1,n=0;n{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var r in e)n.o(e,r)&&!n.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{"use strict";function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);nt.length)&&(e=t.length);for(var n=0,r=new Array(e);nthis.numberSpecification.getMaxFractionDigits()&&(e=e.replace(/0+$/,"")),e.length1&&(o=e(i[1]));var a=!1;o.forEach((function(t){"q"===t.name&&(a=!0)})),a||o.push({name:"q",value:""}),o.forEach((function(e){"q"===e.name&&(e.value+=[e.value.length>0?"/":"",t.data("slider-label"),"-",t.data("slider-unit"),"-",r.values[0],"-",r.values[1]].join(""))}));var u=[i[0],"?",$.param(o)].join("");prestashop.emit("updateFacets",u)},slide:function(e,n){E(t.data("slider-id"),$("#facet_label_".concat(t.data("slider-id"))),n.values[0],n.values[1])}})}))};var O=n(379),_=n.n(O),C=n(580),D=n.n(C);_()(D(),{insert:"head",singleton:!1}),D().locals,$(document).ready((function(){prestashop.on("updateProductList",(function(){$(".faceted-overlay").remove(),I()})),I(),prestashop.on("updateFacets",(function(){1!==$(".faceted-overlay").length&&$("body").append('')}))}));var F=n(765),G=n.n(F);_()(G(),{insert:"head",singleton:!1}),G().locals;var T=n(741),A=n.n(T);_()(A(),{insert:"head",singleton:!1}),A().locals})()})();
-//# sourceMappingURL=front.js.map
\ No newline at end of file
+//# sourceMappingURL=front.js.map
+
+$('.grade-stars-filter').rating();
+
+var oldXHR = window.XMLHttpRequest;
+
+function newXHR() {
+ var realXHR = new oldXHR();
+ realXHR.addEventListener("readystatechange", function() {
+ if(realXHR.readyState===4 && realXHR.status===200){
+ setTimeout(function(){ $('.grade-stars-filter').rating(); }, 50);
+ }
+ }, false);
+ return realXHR;
+}
+window.XMLHttpRequest = newXHR;
From 9a70fda998dc900bc3eb30c56cc158706c33320a Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:46:56 -0600
Subject: [PATCH 09/28] updates facets front view
---
views/templates/front/catalog/facets.tpl | 47 +++++++++++++++++++-----
1 file changed, 38 insertions(+), 9 deletions(-)
diff --git a/views/templates/front/catalog/facets.tpl b/views/templates/front/catalog/facets.tpl
index 72de2874f..3e9f47430 100644
--- a/views/templates/front/catalog/facets.tpl
+++ b/views/templates/front/catalog/facets.tpl
@@ -168,13 +168,42 @@
{$filter.label}
-
-
-
- {/foreach}
- {/block}
- {/if}
-
- {/foreach}
-
+
+
+
+ {/foreach}
+ {/block}
+
+ {elseif $facet.widgetType == 'star'}
+ {block name='facet_item_star'}
+
+ {/block}
+ {/if}
+
+ {/foreach}
+
{/if}
From 21a9f79598e5a51e3b2500b6c2637288b6240116 Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:51:16 -0600
Subject: [PATCH 10/28] adds avg_score to mysql table mapping
---
src/Adapter/MySQL.php | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/Adapter/MySQL.php b/src/Adapter/MySQL.php
index 8e3a33d64..f5bf7b3f8 100644
--- a/src/Adapter/MySQL.php
+++ b/src/Adapter/MySQL.php
@@ -301,6 +301,12 @@ protected function getFieldMapping()
'joinCondition' => '(psales.id_product = p.id_product)',
'joinType' => self::LEFT_JOIN,
],
+ 'avg_score' => [
+ 'tableName' => 'layered_comment_index',
+ 'tableAlias' => 'coms',
+ 'joinCondition' => '(coms.id_product = p.id_product)',
+ 'joinType' => self::INNER_JOIN,
+ ],
];
return $filterToTableMapping;
From 0d6b378c7e03071ece1ccc818c6c071d2e7385e8 Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 13:56:31 -0600
Subject: [PATCH 11/28] updates search
---
src/Product/Search.php | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/src/Product/Search.php b/src/Product/Search.php
index 74e5512ce..ca2653619 100644
--- a/src/Product/Search.php
+++ b/src/Product/Search.php
@@ -280,6 +280,18 @@ private function addSearchFilters($selectedFilters, $parent, $idShop)
);
}
break;
+
+ case 'review':
+ if (isset($selectedFilters['review'])
+ && (
+ $selectedFilters['review'][0] !== ''
+ )
+ ) {
+ $this->addReviewFilter(
+ (float) $selectedFilters['review'][0]
+ );
+ }
+ break;
}
}
@@ -329,4 +341,14 @@ private function addPriceFilter($minPrice, $maxPrice)
$this->getSearchAdapter()->addFilter('price_min', [$maxPrice], '<=');
$this->getSearchAdapter()->addFilter('price_max', [$minPrice], '>=');
}
+
+ /**
+ * Add a review filter
+ *
+ * @param float $scoreUp
+ */
+ private function addReviewFilter($scoreUp)
+ {
+ $this->getSearchAdapter()->addFilter('avg_score', [$scoreUp], '>=');
+ }
}
From 8ee9a3a96bcccb51631e93bf1c665b1a2a310d0d Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 14:24:31 -0600
Subject: [PATCH 12/28] adds review indexer file
---
ps_facetedsearch-review-indexer.php | 36 +++++++++++++++++++++++++++++
ps_facetedsearch.php | 2 ++
2 files changed, 38 insertions(+)
create mode 100755 ps_facetedsearch-review-indexer.php
diff --git a/ps_facetedsearch-review-indexer.php b/ps_facetedsearch-review-indexer.php
new file mode 100755
index 000000000..dd14418ff
--- /dev/null
+++ b/ps_facetedsearch-review-indexer.php
@@ -0,0 +1,36 @@
+
+ * @copyright Since 2007 PrestaShop SA and Contributors
+ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
+ */
+require_once __DIR__ . '/../../config/config.inc.php';
+require_once __DIR__ . '/ps_facetedsearch.php';
+
+if (substr(Tools::encrypt('ps_facetedsearch/index'), 0, 10) != Tools::getValue('token') || !Module::isInstalled('ps_facetedsearch')) {
+ exit('Bad token');
+}
+
+Shop::setContext(Shop::CONTEXT_ALL);
+
+$module = new Ps_Facetedsearch();
+
+if (Tools::getValue('full')){
+ $module->rebuildCommentIndexTable();
+ echo $module->indexReviews(true);
+}else{
+ echo $module->indexReviews();
+}
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index 4df9fb7c7..ac3bfdefe 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -827,6 +827,8 @@ public function getContent()
'full_price_indexer_url' => $moduleUrl . 'ps_facetedsearch-price-indexer.php' . '?token=' . substr(Tools::hash('ps_facetedsearch/index'), 0, 10) . '&full=1',
'attribute_indexer_url' => $moduleUrl . 'ps_facetedsearch-attribute-indexer.php' . '?token=' . substr(Tools::hash('ps_facetedsearch/index'), 0, 10),
'clear_cache_url' => $moduleUrl . 'ps_facetedsearch-clear-cache.php' . '?token=' . substr(Tools::hash('ps_facetedsearch/index'), 0, 10),
+ 'index_reviews_full' => $moduleUrl . 'ps_facetedsearch-review-indexer.php' . '?full=true&token=' . substr(Tools::encrypt('ps_facetedsearch/index'), 0, 10),
+ 'index_reviews_missing' => $moduleUrl . 'ps_facetedsearch-review-indexer.php' . '?token=' . substr(Tools::encrypt('ps_facetedsearch/index'), 0, 10),
'filters_templates' => $this->getDatabase()->executeS('SELECT * FROM ' . _DB_PREFIX_ . 'layered_filter ORDER BY date_add DESC'),
'show_quantities' => Configuration::get('PS_LAYERED_SHOW_QTIES'),
'cache_enabled' => Configuration::get('PS_LAYERED_CACHE_ENABLED'),
From e0494006a21f9af2a40ef9ed4f5831e19ee4827d Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 14:40:41 -0600
Subject: [PATCH 13/28] admin manage view
---
views/templates/admin/manage.tpl | 76 ++++++++++++++++----------------
1 file changed, 39 insertions(+), 37 deletions(-)
mode change 100644 => 100755 views/templates/admin/manage.tpl
diff --git a/views/templates/admin/manage.tpl b/views/templates/admin/manage.tpl
old mode 100644
new mode 100755
index 9290d0aac..cdd983c60
--- a/views/templates/admin/manage.tpl
+++ b/views/templates/admin/manage.tpl
@@ -19,33 +19,35 @@
{include file='./_partials/messages.tpl'}
-
{l s='Indexes and caches' d='Modules.Facetedsearch.Admin'}
-
- {l s='Indexing is in progress. Please do not leave this page' d='Modules.Facetedsearch.Admin'}
-
-
-
-
- {l s='You can set a cron job that will rebuild price index using the following URL:' d='Modules.Facetedsearch.Admin'}
-
-
{$price_indexer_url}
-
-
- {l s='You can set a cron job that will rebuild attribute index using the following URL:' d='Modules.Facetedsearch.Admin'}
-
-
{$attribute_indexer_url}
+
{l s='Indexes and caches' d='Modules.Facetedsearch.Admin'}
+
+ {l s='Indexing is in progress. Please do not leave this page' d='Modules.Facetedsearch.Admin'}
+
+
+
+
+ {l s='You can set a cron job that will rebuild price index using the following URL:' d='Modules.Facetedsearch.Admin'}
+
+ {$price_indexer_url}
+
+
+ {l s='You can set a cron job that will rebuild attribute index using the following URL:' d='Modules.Facetedsearch.Admin'}
+
+ {$attribute_indexer_url}
+
+
+
+
{l s='A nightly rebuild is recommended.' d='Modules.Facetedsearch.Admin'}
-
-
-
{l s='A nightly rebuild is recommended.' d='Modules.Facetedsearch.Admin'}
-
{l s='Filters templates' d='Modules.Facetedsearch.Admin'}{$filters_templates|count}
@@ -252,15 +254,15 @@
var base_folder = '{$base_folder}';
var translations = new Object();
- translations.in_progress = '{l s='(in progress)' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.url_indexation_finished = '{l s='URL indexing finished' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.attribute_indexation_finished = '{l s='Attribute indexing finished' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.url_indexation_failed = '{l s='URL indexing failed' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.attribute_indexation_failed = '{l s='Attribute indexing failed' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.price_indexation_finished = '{l s='Price indexing finished' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.price_indexation_failed = '{l s='Price indexing failed' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.price_indexation_in_progress = '{l s='(in progress, %s products price to index)' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.loading = '{l s='Loading...' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.delete_all_filters_templates = '{l s='You selected -All categories-: all existing filter templates will be deleted. Is it OK?' js=1 d='Modules.Facetedsearch.Admin'}';
- translations.no_selected_categories = '{l s='You must select at least one category' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.in_progress = '{l s='(in progress)' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.url_indexation_finished = '{l s='URL indexing finished' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.attribute_indexation_finished = '{l s='Indexing finished' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.url_indexation_failed = '{l s='URL indexing failed' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.attribute_indexation_failed = '{l s='Indexing failed' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.price_indexation_finished = '{l s='Price indexing finished' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.price_indexation_failed = '{l s='Price indexing failed' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.price_indexation_in_progress = '{l s='(in progress, %s products price to index)' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.loading = '{l s='Loading...' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.delete_all_filters_templates = '{l s='You selected -All categories-: all existing filter templates will be deleted. Is it OK?' js=1 d='Modules.Facetedsearch.Admin'}';
+ translations.no_selected_categories = '{l s='You must select at least one category' js=1 d='Modules.Facetedsearch.Admin'}';
From 90354ff183d628ade9d2ed48a8bf6d7ae2927a2f Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 17:20:33 -0600
Subject: [PATCH 14/28] index valid comments
---
ps_facetedsearch.php | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index ac3bfdefe..3b020a46d 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -1547,14 +1547,18 @@ public function rebuildCommentIndexTable()
public function indexReviews($full = false)
{
if ($full) {
- $query = 'SELECT avg(`grade`) as avg_grade, sum(`grade`) as sum_grade, `id_product` FROM ' . _DB_PREFIX_ . 'product_comment
-group by id_product';
+ $validateCondition = '';
+ if (Configuration::get('PRODUCT_COMMENTS_MODERATE')){
+ $validateCondition = ' where validate = 1';
+ }
+
+ $query = 'SELECT avg(`grade`) as avg_grade, sum(`grade`) as sum_grade, `id_product` FROM ' . _DB_PREFIX_ . 'product_comment '. $validateCondition .' group by id_product';
foreach ($this->getDatabase()->executeS($query) as $comment) {
$this->addCommentIndex($comment);
}
- $query = 'SELECT `id_product_comment`, `id_product` FROM ' . _DB_PREFIX_ . 'product_comment';
+ $query = 'SELECT `id_product_comment`, `id_product` FROM ' . _DB_PREFIX_ . 'product_comment' . $validateCondition;
foreach ($this->getDatabase()->executeS($query) as $commentLog) {
$this->addCommentIndexLog($commentLog);
From aca5aa1536986014a4a453eb2f3ffb3e2cb124cc Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 12 Dec 2021 20:06:33 -0600
Subject: [PATCH 15/28] invalidate block cache after adding comment
---
src/Hook/ProductComment.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Hook/ProductComment.php b/src/Hook/ProductComment.php
index 9c01c30d6..441257934 100755
--- a/src/Hook/ProductComment.php
+++ b/src/Hook/ProductComment.php
@@ -62,6 +62,7 @@ public function actionObjectProductCommentValidateAfter(array $params)
$this->addCommentIndexLog($grade);
}
}
+ $this->module->invalidateLayeredFilterBlockCache();
}
public function addCommentIndexLog($comment){
From 9191b0ff49491ba8f7a01b573611872eaf886927 Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 13 Dec 2021 17:04:02 -0600
Subject: [PATCH 16/28] Update ps_facetedsearch.php spaces
Co-authored-by: GoT
---
ps_facetedsearch.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index 3b020a46d..1dba9958f 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -1171,7 +1171,7 @@ public function buildLayeredCategories()
$sqlInsert .= '(' . (int) $idCategory . ', ' . (int) $idShop . ', ' . (int) str_replace('layered_selection_feat_', '', $key) . ',
\'id_feature\',' . (int) $n . ', ' . (int) $limit . ', ' . (int) $type . '),';
} elseif ($key == 'layered_selection_review_star') {
- $sqlInsert .= '(' . (int) $idCategory . ', ' . (int) $idShop . ', NULL,\'review\',' . (int) $n . ', ' . (int) $limit . ', ' . (int) $type . '),';
+ $sqlInsert .= '(' . (int) $idCategory . ', ' . (int) $idShop . ', NULL, \'review\', ' . (int) $n . ', ' . (int) $limit . ', ' . (int) $type . '),';
}
++$nbSqlValuesToInsert;
From c13edac6f378a8883f0c7fb0aa02942c42b6a450 Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 13 Dec 2021 17:04:46 -0600
Subject: [PATCH 17/28] Update ps_facetedsearch.php float avg_score
Co-authored-by: GoT
---
ps_facetedsearch.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index 1dba9958f..16b23a8d9 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -1527,7 +1527,7 @@ public function rebuildCommentIndexTable()
'CREATE TABLE `' . _DB_PREFIX_ . 'layered_comment_index` (
`id_product` INT NOT NULL,
`score` INT NOT NULL,
- `avg_score` FLOAT NOT NULL,
+ `avg_score` FLOAT(5, 4) NOT NULL,
PRIMARY KEY (`id_product`),
INDEX `score` (`score`),
INDEX `avg_score` (`score`)
From e79531f5acca6d3529a42af100f27f5831c8c9f6 Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 13 Dec 2021 17:05:08 -0600
Subject: [PATCH 18/28] Update ps_facetedsearch.php space sql create
Co-authored-by: GoT
---
ps_facetedsearch.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index 16b23a8d9..1a63efcc3 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -1525,7 +1525,7 @@ public function rebuildCommentIndexTable()
$this->getDatabase()->execute(
'CREATE TABLE `' . _DB_PREFIX_ . 'layered_comment_index` (
- `id_product` INT NOT NULL,
+ `id_product` INT NOT NULL,
`score` INT NOT NULL,
`avg_score` FLOAT(5, 4) NOT NULL,
PRIMARY KEY (`id_product`),
From 501fa80c287bc82adabf68b541919f90aae21a92 Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 13 Dec 2021 17:05:23 -0600
Subject: [PATCH 19/28] Update ps_facetedsearch.php space
Co-authored-by: GoT
---
ps_facetedsearch.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index 1a63efcc3..4dc3d5603 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -1536,8 +1536,8 @@ public function rebuildCommentIndexTable()
$this->getDatabase()->execute(
'CREATE TABLE `' . _DB_PREFIX_ . 'layered_comment_index_log` (
- `id_comment` INT NOT NULL,
- `id_product` INT NOT NULL,
+ `id_comment` INT NOT NULL,
+ `id_product` INT NOT NULL,
`indexed` TINYINT(1) NOT NULL,
PRIMARY KEY (`id_comment`)
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;'
From b8cb6a1ebc25c1c5f8e25dd84d56d7373ef6817f Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 13 Dec 2021 17:06:48 -0600
Subject: [PATCH 20/28] ps prefix and beautify sql query
Co-authored-by: GoT
---
ps_facetedsearch.php | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index 4dc3d5603..88f5b1bbe 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -1565,10 +1565,11 @@ public function indexReviews($full = false)
}
} else {
- $query = 'select pc.id_product_comment, pc.id_product, pc.grade from ps_product_comment as pc
-left join ps_layered_comment_index_log as lc
-on pc.id_product_comment = lc.id_comment
-where lc.indexed is null;';
+ $query = 'SELECT pc.id_product_comment, pc.id_product, pc.grade ' .
+ 'FROM ' . _DB_PREFIX_ . '_product_comment as pc ' .
+ 'LEFT JOIN ' . _DB_PREFIX_ . '_layered_comment_index_log as lc ' .
+ 'pc.id_product_comment = lc.id_comment ' .
+ 'WHERE lc.indexed IS NULL';
//returns non matching records
foreach ($this->getDatabase()->executeS($query) as $commentLog) {
From ba9c0201274ee95a250a7b65a3a9637cd5410f77 Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 13 Dec 2021 17:10:23 -0600
Subject: [PATCH 21/28] removes useless if condition
Co-authored-by: GoT
---
src/Hook/ProductComment.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Hook/ProductComment.php b/src/Hook/ProductComment.php
index 441257934..181bb03f9 100755
--- a/src/Hook/ProductComment.php
+++ b/src/Hook/ProductComment.php
@@ -44,7 +44,7 @@ public function actionObjectProductCommentValidateAfter(array $params)
$gradeCommentRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index`
WHERE id_product =' . $grade->id_product);
- if (empty($gradeCommentRow) || !$gradeCommentRow){
+ if (empty($gradeCommentRow)){
//insert the first index record for this comment
$this->database->execute('INSERT INTO `'._DB_PREFIX_.'layered_comment_index` (`id_product`, `score`, `avg_score`) VALUES ('.$grade->id_product.', '.$grade->grade.','.$grade->grade.')');
From c3eeabe669a558e4d60f4f1d6902f2d4b24ad451 Mon Sep 17 00:00:00 2001
From: Sam
Date: Mon, 13 Dec 2021 17:27:51 -0600
Subject: [PATCH 22/28] get category id with getValue
---
src/Filters/Block.php | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/Filters/Block.php b/src/Filters/Block.php
index 8889e1891..1bf8ef655 100644
--- a/src/Filters/Block.php
+++ b/src/Filters/Block.php
@@ -1000,6 +1000,11 @@ private function getReviweBlock($filter, $selectedFilters)
'1' => ['name'=>"1"],
];
+ $idParent = (int) Tools::getValue(
+ 'id_category',
+ Tools::getValue('id_category_layered', Configuration::get('PS_HOME_CATEGORY'))
+ );
+
$query = 'SELECT count(g.grade) as count ,g.grade FROM (SELECT t.id_product, case
when t.avg_grade between 1 and 1.99 then "1"
when t.avg_grade between 2 and 2.99 then "2"
@@ -1009,7 +1014,7 @@ private function getReviweBlock($filter, $selectedFilters)
FROM (SELECT avg(h.grade) as avg_grade,
h.id_product FROM
(select pc.id_product, pc.grade from ' . _DB_PREFIX_ . 'product_comment as pc
-inner join (SELECT * FROM ' . _DB_PREFIX_ . 'category_product where id_category = '.$_GET['id_category'].') cp
+inner join (SELECT * FROM ' . _DB_PREFIX_ . 'category_product where id_category = '.$idParent.') cp
on pc.id_product = cp.id_product) h
group by id_product) t) g
group by g.grade
From e3754c194d238e0da0610519b367bfb257e3ffb7 Mon Sep 17 00:00:00 2001
From: Sam
Date: Wed, 15 Dec 2021 14:50:33 -0600
Subject: [PATCH 23/28] removes review filters when product comments module is
disabled
---
ps_facetedsearch-review-indexer.php | 4 +++
ps_facetedsearch.php | 16 ++++++++---
views/templates/admin/add.tpl | 42 +++++++++++++++--------------
views/templates/admin/manage.tpl | 6 +++--
4 files changed, 42 insertions(+), 26 deletions(-)
diff --git a/ps_facetedsearch-review-indexer.php b/ps_facetedsearch-review-indexer.php
index dd14418ff..36792af4b 100755
--- a/ps_facetedsearch-review-indexer.php
+++ b/ps_facetedsearch-review-indexer.php
@@ -24,6 +24,10 @@
exit('Bad token');
}
+if (!Module::isEnabled('productcomments')){
+ exit('Product Comment module is not installed or is disabled.');
+}
+
Shop::setContext(Shop::CONTEXT_ALL);
$module = new Ps_Facetedsearch();
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index 88f5b1bbe..b72b4e781 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -144,7 +144,7 @@ public function getContext()
protected function getDefaultFilters()
{
- return [
+ $defaultFilters = [
'layered_selection_subcategories' => [
'label' => 'Sub-categories filter',
],
@@ -165,11 +165,16 @@ protected function getDefaultFilters()
'label' => 'Product price filter (slider)',
'slider' => true,
],
- 'layered_selection_review_star' => [
+ ];
+
+ if (Module::isEnabled('productcomments')){
+ $defaultFilters['layered_selection_review_star'] = [
'label' => 'Avg. Customer Review',
'star' => true
- ],
- ];
+ ];
+ }
+
+ return $defaultFilters;
}
public function install()
@@ -778,6 +783,7 @@ public function getContent()
]);
$this->context->smarty->assign('categories_tree', $treeCategoriesHelper->render());
+ $this->context->smarty->assign('comment_module_enabled', Module::isEnabled('productcomments'));
return $this->display(__FILE__, 'views/templates/admin/add.tpl');
}
@@ -841,6 +847,8 @@ public function getContent()
'filter_by_default_category' => (bool) Configuration::get('PS_LAYERED_FILTER_BY_DEFAULT_CATEGORY'),
]);
+ $this->context->smarty->assign('comment_module_enabled', Module::isEnabled('productcomments'));
+
return $this->display(__FILE__, 'views/templates/admin/manage.tpl');
}
diff --git a/views/templates/admin/add.tpl b/views/templates/admin/add.tpl
index 9b90a4fe4..e194c486b 100755
--- a/views/templates/admin/add.tpl
+++ b/views/templates/admin/add.tpl
@@ -220,30 +220,32 @@
-
-
From 745d289a214a4d347c7a9630b5fe34fc9df046a0 Mon Sep 17 00:00:00 2001
From: Sam Berry
Date: Mon, 20 Jun 2022 09:16:11 -0400
Subject: [PATCH 24/28] feat: support for add after and delete after comment
indexing
---
src/Hook/ProductComment.php | 105 ++++++++++++++++++++++++++++++------
1 file changed, 88 insertions(+), 17 deletions(-)
diff --git a/src/Hook/ProductComment.php b/src/Hook/ProductComment.php
index 181bb03f9..25355dc4a 100755
--- a/src/Hook/ProductComment.php
+++ b/src/Hook/ProductComment.php
@@ -23,49 +23,120 @@
class ProductComment extends AbstractHook
{
const AVAILABLE_HOOKS = [
- 'actionObjectProductCommentValidateAfter',
+ 'actionObjectProductCommentAddAfter',
+ 'actionObjectProductCommentDeleteAfter',
+ 'actionObjectProductCommentValidateAfter'
];
/**
- * Product Comment Validate After
+ * Product Add After
*
- * Smart index after validating a comment
+ * Smart index after adding a comment
*
* @param array $params
*/
- public function actionObjectProductCommentValidateAfter(array $params)
+ public function actionObjectProductCommentAddAfter(array $params)
{
- $grade = $params['object'];
+ if (!\Configuration::get('PRODUCT_COMMENTS_MODERATE')){
+ $this->updateCommentIndex($params['array']);
+ }
+ }
+
+ /**
+ * Product Validate After
+ *
+ * Smart index after validating a comment
+ *
+ * @param array $params
+ */
+ public function actionObjectProductCommentValidateAfter(array $params){
+ if (\Configuration::get('PRODUCT_COMMENTS_MODERATE')){
+ $this->updateCommentIndex($params['object']);
+ }
+ }
+
+ /**
+ * Product Delete After
+ *
+ * Smart index after deleting a comment
+ *
+ * @param array $params
+ */
+ public function actionObjectProductCommentDeleteAfter(array $params){
+ $comment = $params['object']; $skip = false;
+
+ if (\Configuration::get('PRODUCT_COMMENTS_MODERATE')){
+ if ((int)$comment->validate){
+ $skip = true;
+ }
+ }
+
+ if ($skip){
+ $gradeCommentRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index`
+ WHERE id_product =' . $comment->id_product);
+
+ //update index for the comment
+ $productCommentLogRowCount = $this->database->executeS('SELECT count(id_comment) as count FROM `' . _DB_PREFIX_ . 'layered_comment_index_log`
+ WHERE id_product = ' . $comment->id_product . ' AND indexed = 1');
+
+ $count = $productCommentLogRowCount[0]['count'];
+ $count--;
+
+ $newGradeValue = (int)$gradeCommentRow[0]['score'] - (int)$comment->grade;
+ $avg_score = $newGradeValue/(((int)$count));
+
+ $this->database->execute('update ' . _DB_PREFIX_ . 'layered_comment_index set score='.$newGradeValue.', avg_score= '.$avg_score .' where id_product=' . $comment->id_product);
+
+ $this->deleteCommentIndexLog($comment->id, $comment->id_product);
+ }
+ }
+
+ public function updateCommentIndex($param){
+ if (is_array($param)){
+ $grade = $param['grade'];
+ $id_product = $param['id_product'];
+ $id_comment = $param['id_product_comment'];
+ }else{
+ $grade = $param->grade;
+ $id_product = $param->id_product;
+ $id_comment = $param->id;
+ }
$commentLogRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index_log`
- WHERE id_comment = ' . $grade->id . ' AND indexed = 1');
+ WHERE id_comment = ' . $id_comment . ' AND indexed = 1');
if (empty($commentLogRow)){
$gradeCommentRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index`
- WHERE id_product =' . $grade->id_product);
+ WHERE id_product =' . $id_product);
if (empty($gradeCommentRow)){
//insert the first index record for this comment
- $this->database->execute('INSERT INTO `'._DB_PREFIX_.'layered_comment_index` (`id_product`, `score`, `avg_score`) VALUES ('.$grade->id_product.', '.$grade->grade.','.$grade->grade.')');
+ $this->database->execute('INSERT INTO `'._DB_PREFIX_.'layered_comment_index` (`id_product`, `score`, `avg_score`) VALUES ('.$id_product.', '.$grade.','.$grade.')');
- $this->addCommentIndexLog($grade);
+ $this->addCommentIndexLog($id_comment, $id_product);
}else{
//update index for the comment
- $productCommentLogRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index_log`
- WHERE id_product = ' . $grade->id_product . ' AND indexed = 1');
+ $productCommentLogRowCount = $this->database->executeS('SELECT count(id_comment) as count FROM `' . _DB_PREFIX_ . 'layered_comment_index_log`
+ WHERE id_product = ' . $id_product . ' AND indexed = 1');
+
+ $count = $productCommentLogRowCount[0]['count'];
- $newGradeValue = (int)$gradeCommentRow[0]['score'] + (int)$grade->grade;
- $avg_score = $newGradeValue/(count($productCommentLogRow)+1);
+ $newGradeValue = (int)$gradeCommentRow[0]['score'] + (int)$grade;
+ $avg_score = $newGradeValue/(((int)$count)+1);
- $this->database->execute('update ' . _DB_PREFIX_ . 'layered_comment_index set score='.$newGradeValue.', avg_score= '.$avg_score .' where id_product=' . $grade->id_product);
+ $this->database->execute('update ' . _DB_PREFIX_ . 'layered_comment_index set score='.$newGradeValue.', avg_score= '.$avg_score .' where id_product=' . $id_product);
- $this->addCommentIndexLog($grade);
+ $this->addCommentIndexLog($id_comment, $id_product);
}
}
$this->module->invalidateLayeredFilterBlockCache();
}
- public function addCommentIndexLog($comment){
- $this->database->execute('INSERT INTO `'._DB_PREFIX_.'layered_comment_index_log` (`id_comment`, `indexed`, `id_product`) VALUES ('.$comment->id.', 1,'. $comment->id_product .')');
+ public function addCommentIndexLog($id_comment, $id_product){
+ $this->database->execute('INSERT INTO `'._DB_PREFIX_.'layered_comment_index_log` (`id_comment`, `indexed`, `id_product`) VALUES ('.$id_comment.', 1,'. $id_product .')');
+ }
+
+ public function deleteCommentIndexLog($id_comment, $id_product){
+ $this->database->execute('DELETE FROM `'._DB_PREFIX_.'layered_comment_index_log` WHERE id_comment = ' . $id_comment . ' AND id_product = ' . $id_product);
}
}
From 0073146afd28a44f397991ec241a50ff798d83fc Mon Sep 17 00:00:00 2001
From: Sam Berry
Date: Mon, 20 Jun 2022 12:56:07 -0400
Subject: [PATCH 25/28] fix: a little fix in if condition
---
src/Hook/ProductComment.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Hook/ProductComment.php b/src/Hook/ProductComment.php
index 25355dc4a..1ba324912 100755
--- a/src/Hook/ProductComment.php
+++ b/src/Hook/ProductComment.php
@@ -66,12 +66,12 @@ public function actionObjectProductCommentDeleteAfter(array $params){
$comment = $params['object']; $skip = false;
if (\Configuration::get('PRODUCT_COMMENTS_MODERATE')){
- if ((int)$comment->validate){
+ if (!(int)$comment->validate){
$skip = true;
}
}
- if ($skip){
+ if (!$skip){
$gradeCommentRow = $this->database->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'layered_comment_index`
WHERE id_product =' . $comment->id_product);
From 0a022417a0ab6574f19a1ccb16423b63f3c56156 Mon Sep 17 00:00:00 2001
From: Sam Berry
Date: Mon, 20 Jun 2022 15:14:47 -0400
Subject: [PATCH 26/28] fix: added check for comment approval
---
ps_facetedsearch.php | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index b72b4e781..211ed4e2f 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -1573,11 +1573,16 @@ public function indexReviews($full = false)
}
} else {
+ $validateCondition = '';
+ if (Configuration::get('PRODUCT_COMMENTS_MODERATE')){
+ $validateCondition = ' AND WHERE validate = 1';
+ }
+
$query = 'SELECT pc.id_product_comment, pc.id_product, pc.grade ' .
'FROM ' . _DB_PREFIX_ . '_product_comment as pc ' .
'LEFT JOIN ' . _DB_PREFIX_ . '_layered_comment_index_log as lc ' .
'pc.id_product_comment = lc.id_comment ' .
- 'WHERE lc.indexed IS NULL';
+ 'WHERE lc.indexed IS NULL' . $validateCondition;
//returns non matching records
foreach ($this->getDatabase()->executeS($query) as $commentLog) {
From 3160ebd75b768920111d55a0c63be28ff26f9ea2 Mon Sep 17 00:00:00 2001
From: Sam Berry
Date: Tue, 12 Jul 2022 17:59:17 -0400
Subject: [PATCH 27/28] fix: removed the index record on last comment removal
for a product
---
src/Hook/ProductComment.php | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/Hook/ProductComment.php b/src/Hook/ProductComment.php
index 1ba324912..5640a5b91 100755
--- a/src/Hook/ProductComment.php
+++ b/src/Hook/ProductComment.php
@@ -82,10 +82,14 @@ public function actionObjectProductCommentDeleteAfter(array $params){
$count = $productCommentLogRowCount[0]['count'];
$count--;
- $newGradeValue = (int)$gradeCommentRow[0]['score'] - (int)$comment->grade;
- $avg_score = $newGradeValue/(((int)$count));
+ if ($count === 0 ){
+ $this->database->execute('DELETE FROM `'._DB_PREFIX_.'layered_comment_index` WHERE id_product = ' . $comment->id_product );
+ } else{
+ $newGradeValue = (int)$gradeCommentRow[0]['score'] - (int)$comment->grade;
+ $avg_score = $newGradeValue/(((int)$count));
- $this->database->execute('update ' . _DB_PREFIX_ . 'layered_comment_index set score='.$newGradeValue.', avg_score= '.$avg_score .' where id_product=' . $comment->id_product);
+ $this->database->execute('update ' . _DB_PREFIX_ . 'layered_comment_index set score='.$newGradeValue.', avg_score= '.$avg_score .' where id_product=' . $comment->id_product);
+ }
$this->deleteCommentIndexLog($comment->id, $comment->id_product);
}
From 4f79cb81b52cc5fb780c48098c6ed41b90779f6f Mon Sep 17 00:00:00 2001
From: Sam Berry
Date: Mon, 5 Sep 2022 08:19:27 -0400
Subject: [PATCH 28/28] chore: change version to 3.9.0
---
ps_facetedsearch.php | 2 +-
upgrade/upgrade-3.9.0.php | 32 ++++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 1 deletion(-)
create mode 100644 upgrade/upgrade-3.9.0.php
diff --git a/ps_facetedsearch.php b/ps_facetedsearch.php
index 211ed4e2f..1fb71c774 100644
--- a/ps_facetedsearch.php
+++ b/ps_facetedsearch.php
@@ -91,7 +91,7 @@ public function __construct()
{
$this->name = 'ps_facetedsearch';
$this->tab = 'front_office_features';
- $this->version = '3.8.0';
+ $this->version = '3.9.0';
$this->author = 'PrestaShop';
$this->need_instance = 0;
$this->bootstrap = true;
diff --git a/upgrade/upgrade-3.9.0.php b/upgrade/upgrade-3.9.0.php
new file mode 100644
index 000000000..bc4e0b248
--- /dev/null
+++ b/upgrade/upgrade-3.9.0.php
@@ -0,0 +1,32 @@
+
+ * @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_3_9_0(Ps_Facetedsearch $module)
+{
+ $module->rebuildCommentIndexTable();
+ $module->indexReviews(true);
+ $module->rebuildLayeredStructure();
+ $module->invalidateLayeredFilterBlockCache();
+
+ return $module->registerHook($module->getHookDispatcher()->getAvailableHooks());
+}