Jump to content

[solved] Faceted module missing features (without predefined values)


GaetanV

Recommended Posts

Hello,

In the faceted module I don't have access to all the product features.

I've rebuilt the index, cleared the module and site cache, but the missing features still don't show up.

Is there something that can prevent the display of a characteristic or is it a bug?

Thank you for your help.

filters-aviables.png

features.png

Edited by GaetanV (see edit history)
Link to comment
Share on other sites

Problem fixed...

The faceted module does not allow searching on characteristics that do not have predefined values.

To avoid this behavior, you must authorize the module to list the characteristics that do not have default values by overriding the file:

modules\ps_facetedsearch\ps_facetedsearch.php

For this add the file:

override\modules\ps_facetedsearch\ps_facetedsearch.php

With this content:

<?php

class Ps_FacetedsearchOverride extends Ps_Facetedsearch {
    
    /**
     * @var int
     */
    private $psLayeredFullTree;

    public function getContent()
    {
        global $cookie;
        $message = '';

        if (Tools::isSubmit('SubmitFilter')) {
            if (!Tools::getValue('layered_tpl_name')) {
                $message = $this->displayError($this->trans('Filter template name required (cannot be empty)', [], 'Modules.Facetedsearch.Admin'));
            } elseif (!Tools::getValue('categoryBox')) {
                $message = $this->displayError($this->trans('You must select at least one category.', [], 'Modules.Facetedsearch.Admin'));
            } else {
                // Get or generate id
                $idLayeredFilter = (int) Tools::getValue('id_layered_filter');
                if (Tools::getValue('scope')) {
                    $this->getDatabase()->execute('TRUNCATE TABLE ' . _DB_PREFIX_ . 'layered_filter');
                    $categories = $this->getDatabase()->executeS(
                        'SELECT id_category FROM ' . _DB_PREFIX_ . 'category'
                    );

                    foreach ($categories as $category) {
                        $_POST['categoryBox'][] = (int) $category['id_category'];
                    }
                }

                // Associate Shops
                if (isset($_POST['checkBoxShopAsso_layered_filter'])) {
                    $shopList = [];
                    foreach ($_POST['checkBoxShopAsso_layered_filter'] as $idShop => $row) {
                        $assos[] = ['id_shop' => (int) $idShop];
                        $shopList[] = (int) $idShop;
                    }
                } else {
                    $shopList = [(int) $this->getContext()->shop->id];
                }

                if (!empty($_POST['categoryBox']) && is_array($_POST['categoryBox'])) {
                    /* Clean categoryBox before use */
                    $_POST['categoryBox'] = array_map('intval', $_POST['categoryBox']);
                    $filterValues = [
                        'shop_list' => $shopList,
                    ];

                    foreach ($_POST['categoryBox'] as $idCategoryLayered) {
                        $filterValues['categories'][] = $idCategoryLayered;
                    }

                    foreach ($_POST as $key => $value) {
                        if (!preg_match('~^(?P<key>layered_selection_.*)(?<!_filter_)(?<!type)(?<!show_limit)$~', $key, $matches)) {
                            continue;
                        }

                        $filterValues[$matches['key']] = [
                            'filter_type' => (int) Tools::getValue($matches['key'] . '_filter_type', 0),
                            'filter_show_limit' => (int) Tools::getValue($matches['key'] . '_filter_show_limit', 0),
                        ];
                    }

                    $values = [
                        'name' => pSQL(Tools::getValue('layered_tpl_name')),
                        'filters' => pSQL(serialize($filterValues)),
                        'n_categories' => (int) count($filterValues['categories']),
                    ];

                    if (!$idLayeredFilter) {
                        $values['date_add'] = date('Y-m-d H:i:s');
                        $sql = 'INSERT INTO ' . _DB_PREFIX_ . 'layered_filter ' .
                             '(name, filters, n_categories, date_add, id_layered_filter) ' .
                             'VALUES (' .
                             '"' . pSQL($values['name']) . '", ' .
                             '"' . $values['filters'] . '", ' .
                             '' . (int) $values['n_categories'] . ', ' .
                             '"' . pSQL($values['date_add']) . '", ' .
                             '' . $idLayeredFilter . ')';
                        $this->getDatabase()->execute($sql);
                        $idLayeredFilter = (int) $this->getDatabase()->Insert_ID();
                    } else {
                        $this->getDatabase()->execute(
                            'DELETE FROM ' . _DB_PREFIX_ . 'layered_filter_shop WHERE `id_layered_filter` = ' . (int) $idLayeredFilter
                        );
                        $sql = 'UPDATE ' . _DB_PREFIX_ . 'layered_filter ' .
                             'SET name = "' . pSQL($values['name']) . '", ' .
                             'filters = "' . $values['filters'] . '", ' .
                             'n_categories = ' . (int) $values['n_categories'] . ' ' .
                             'WHERE id_layered_filter = ' . $idLayeredFilter;
                        $this->getDatabase()->execute($sql);
                    }

                    if (isset($assos)) {
                        foreach ($assos as $asso) {
                            $this->getDatabase()->execute(
                                'INSERT INTO ' . _DB_PREFIX_ . 'layered_filter_shop (`id_layered_filter`, `id_shop`)
    VALUES(' . $idLayeredFilter . ', ' . (int) $asso['id_shop'] . ')'
                            );
                        }
                    }

                    $this->buildLayeredCategories();
                    $message = $this->displayConfirmation(
                        $this->trans('Your filter', [], 'Modules.Facetedsearch.Admin') . ' "' .
                        Tools::safeOutput(Tools::getValue('layered_tpl_name')) . '" ' .
                        (
                            !empty($_POST['id_layered_filter']) ?
                            $this->trans('was updated successfully.', [], 'Modules.Facetedsearch.Admin') :
                            $this->trans('was added successfully.', [], 'Modules.Facetedsearch.Admin')
                        )
                    );
                }
            }
        } elseif (Tools::isSubmit('submitLayeredSettings')) {
            Configuration::updateValue('PS_LAYERED_CACHE_ENABLED', (int) Tools::getValue('ps_layered_cache_enabled'));
            Configuration::updateValue('PS_LAYERED_SHOW_QTIES', (int) Tools::getValue('ps_layered_show_qties'));
            Configuration::updateValue('PS_LAYERED_FULL_TREE', (int) Tools::getValue('ps_layered_full_tree'));
            Configuration::updateValue('PS_LAYERED_FILTER_PRICE_USETAX', (int) Tools::getValue('ps_layered_filter_price_usetax'));
            Configuration::updateValue('PS_LAYERED_FILTER_CATEGORY_DEPTH', (int) Tools::getValue('ps_layered_filter_category_depth'));
            Configuration::updateValue('PS_LAYERED_FILTER_PRICE_ROUNDING', (int) Tools::getValue('ps_layered_filter_price_rounding'));
            Configuration::updateValue('PS_LAYERED_FILTER_SHOW_OUT_OF_STOCK_LAST', (int) Tools::getValue('ps_layered_filter_show_out_of_stock_last'));
            Configuration::updateValue('PS_LAYERED_FILTER_BY_DEFAULT_CATEGORY', (int) Tools::getValue('ps_layered_filter_by_default_category'));

            $this->psLayeredFullTree = (int) Tools::getValue('ps_layered_full_tree');

            $message = '<div class="alert alert-success">' . $this->trans('Settings saved successfully', [], 'Modules.Facetedsearch.Admin') . '</div>';
            $this->invalidateLayeredFilterBlockCache();
        } elseif (Tools::getValue('deleteFilterTemplate')) {
            $layered_values = $this->getDatabase()->getValue(
                'SELECT filters
                FROM ' . _DB_PREFIX_ . 'layered_filter
                WHERE id_layered_filter = ' . (int) Tools::getValue('id_layered_filter')
            );

            if ($layered_values) {
                $this->getDatabase()->execute(
                    'DELETE FROM ' . _DB_PREFIX_ . 'layered_filter
                    WHERE id_layered_filter = ' . (int) Tools::getValue('id_layered_filter') . ' LIMIT 1'
                );
                $this->buildLayeredCategories();
                $message = $this->displayConfirmation($this->trans('Filter template deleted, categories updated (reverted to default Filter template).', [], 'Modules.Facetedsearch.Admin'));
            } else {
                $message = $this->displayError($this->trans('Filter template not found', [], 'Modules.Facetedsearch.Admin'));
            }
        }

        $categoryBox = [];
        $attributeGroups = $this->getDatabase()->executeS(
            'SELECT ag.id_attribute_group, ag.is_color_group, agl.name, COUNT(DISTINCT(a.id_attribute)) n
            FROM ' . _DB_PREFIX_ . 'attribute_group ag
            LEFT JOIN ' . _DB_PREFIX_ . 'attribute_group_lang agl ON (agl.id_attribute_group = ag.id_attribute_group)
            LEFT JOIN ' . _DB_PREFIX_ . 'attribute a ON (a.id_attribute_group = ag.id_attribute_group)
            WHERE agl.id_lang = ' . (int) $cookie->id_lang . '
            GROUP BY ag.id_attribute_group'
        );

        $features = $this->getDatabase()->executeS(
            'SELECT fl.id_feature, fl.name, COUNT(DISTINCT(fv.id_feature_value)) n
            FROM ' . _DB_PREFIX_ . 'feature_lang fl
            LEFT JOIN ' . _DB_PREFIX_ . 'feature_value fv ON (fv.id_feature = fl.id_feature)
            WHERE fl.id_lang = ' . (int) $cookie->id_lang . '
            GROUP BY fl.id_feature'
        );

        if (Shop::isFeatureActive() && count(Shop::getShops(true, null, true)) > 1) {
            $helper = new HelperForm();
            $helper->id = Tools::getValue('id_layered_filter', null);
            $helper->table = 'layered_filter';
            $helper->identifier = 'id_layered_filter';
            $this->context->smarty->assign('asso_shops', $helper->renderAssoShop());
        }

        $treeCategoriesHelper = new HelperTreeCategories('categories-treeview');
        $treeCategoriesHelper->setRootCategory((Shop::getContext() == Shop::CONTEXT_SHOP ? Category::getRootCategory()->id_category : 0))
                                                                     ->setUseCheckBox(true);

        $moduleUrl = Tools::getProtocol(Tools::usingSecureMode()) . $_SERVER['HTTP_HOST'] . $this->getPathUri();

        if (method_exists($this->context->controller, 'addJquery')) {
            $this->context->controller->addJS(_PS_JS_DIR_ . 'jquery/plugins/jquery.sortable.js');
        }

        $this->context->controller->addJS($this->_path . 'views/dist/back.js');
        $this->context->controller->addCSS($this->_path . 'views/dist/back.css');

        if (Tools::getValue('add_new_filters_template')) {
            $this->context->smarty->assign([
                'current_url' => $this->context->link->getAdminLink('AdminModules') . '&configure=ps_facetedsearch&tab_module=front_office_features&module_name=ps_facetedsearch',
                'uri' => $this->getPathUri(),
                'id_layered_filter' => 0,
                'template_name' => sprintf($this->trans('My template - %s', [], 'Modules.Facetedsearch.Admin'), date('Y-m-d')),
                'attribute_groups' => $attributeGroups,
                'features' => $features,
                'total_filters' => 6 + count($attributeGroups) + count($features),
            ]);

            $this->context->smarty->assign('categories_tree', $treeCategoriesHelper->render());

            return $this->display(__FILE__, 'views/templates/admin/add.tpl');
        }

        if (Tools::getValue('edit_filters_template')) {
            $idLayeredFilter = (int) Tools::getValue('id_layered_filter');
            $template = $this->getDatabase()->getRow(
                'SELECT *
                FROM `' . _DB_PREFIX_ . 'layered_filter`
                WHERE id_layered_filter = ' . $idLayeredFilter
            );

            if (!empty($template)) {
                $filters = Tools::unSerialize($template['filters']);
                $treeCategoriesHelper->setSelectedCategories($filters['categories']);
                $this->context->smarty->assign('categories_tree', $treeCategoriesHelper->render());

                $selectShops = $filters['shop_list'];
                unset($filters['categories']);
                unset($filters['shop_list']);

                $this->context->smarty->assign([
                    'current_url' => $this->context->link->getAdminLink('AdminModules') . '&configure=ps_facetedsearch&tab_module=front_office_features&module_name=ps_facetedsearch',
                    'uri' => $this->getPathUri(),
                    'id_layered_filter' => $idLayeredFilter,
                    'template_name' => $template['name'],
                    'attribute_groups' => $attributeGroups,
                    'features' => $features,
                    'filters' => $filters,
                    'total_filters' => 6 + count($attributeGroups) + count($features),
                    'default_filters' => $this->getDefaultFilters(),
                ]);

                return $this->display(__FILE__, 'views/templates/admin/view.tpl');
            }
        }
        if(!isset($this->psLayeredFullTree)) {
            $this->psLayeredFullTree = (int) Configuration::get('PS_LAYERED_FULL_TREE');;
        }

        $this->context->smarty->assign([
            'message' => $message,
            'uri' => $this->getPathUri(),
            'PS_LAYERED_INDEXED' => (int) Configuration::getGlobalValue('PS_LAYERED_INDEXED'),
            'current_url' => Tools::safeOutput(preg_replace('/&deleteFilterTemplate=[0-9]*&id_layered_filter=[0-9]*/', '', $_SERVER['REQUEST_URI'])),
            'id_lang' => $this->getContext()->cookie->id_lang,
            'token' => substr(Tools::hash('ps_facetedsearch/index'), 0, 10),
            'base_folder' => urlencode(_PS_ADMIN_DIR_),
            'price_indexer_url' => $moduleUrl . 'ps_facetedsearch-price-indexer.php' . '?token=' . substr(Tools::hash('ps_facetedsearch/index'), 0, 10),
            '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),
            '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'),
            'full_tree' => $this->psLayeredFullTree,
            'category_depth' => Configuration::get('PS_LAYERED_FILTER_CATEGORY_DEPTH'),
            'price_use_tax' => (bool) Configuration::get('PS_LAYERED_FILTER_PRICE_USETAX'),
            'limit_warning' => $this->displayLimitPostWarning(21 + count($attributeGroups) * 3 + count($features) * 3),
            'price_use_rounding' => (bool) Configuration::get('PS_LAYERED_FILTER_PRICE_ROUNDING'),
            'show_out_of_stock_last' => (bool) Configuration::get('PS_LAYERED_FILTER_SHOW_OUT_OF_STOCK_LAST'),
            'filter_by_default_category' => (bool) Configuration::get('PS_LAYERED_FILTER_BY_DEFAULT_CATEGORY'),
        ]);

        return $this->display(__FILE__, 'views/templates/admin/manage.tpl');
    }
}

the only modification made in the new field is the replacement of the request:

        $features = $this->getDatabase()->executeS(
            'SELECT fl.id_feature, fl.name, COUNT(DISTINCT(fv.id_feature_value)) n
            FROM ' . _DB_PREFIX_ . 'feature_lang fl
            LEFT JOIN ' . _DB_PREFIX_ . 'feature_value fv ON (fv.id_feature = fl.id_feature)
            WHERE (fv.custom IS NULL OR fv.custom = 0) AND fl.id_lang = ' . (int) $cookie->id_lang . '
            GROUP BY fl.id_feature'
        );

By:

        $features = $this->getDatabase()->executeS(
            'SELECT fl.id_feature, fl.name, COUNT(DISTINCT(fv.id_feature_value)) n
            FROM ' . _DB_PREFIX_ . 'feature_lang fl
            LEFT JOIN ' . _DB_PREFIX_ . 'feature_value fv ON (fv.id_feature = fl.id_feature)
            WHERE fl.id_lang = ' . (int) $cookie->id_lang . '
            GROUP BY fl.id_feature'
        );

All features are now accessible from the faceted module backoffice  😉

Edit : Attention ! All custom values will be displayed, even if several custom values are identical, they will all be displayed.

Edited by GaetanV (see edit history)
Link to comment
Share on other sites

  • GaetanV changed the title to [solved] Faceted module missing features (without predefined values)

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...