* @copyright 2007-2015 Leotheme * @license http://leotheme.com - prestashop template provider */ if (!defined('_PS_VERSION_')) { # module validation exit; } if (file_exists(_PS_MODULE_DIR_ . 'leoproductsearch/classes/LeoSearchProductSearchProvider.php')) { require_once(_PS_MODULE_DIR_ . 'leoproductsearch/classes/LeoSearchProductSearchProvider.php'); } use PrestaShop\PrestaShop\Core\Module\WidgetInterface; // use PrestaShop\PrestaShop\Adapter\Category\CategoryProductSearchProvider; use PrestaShop\PrestaShop\Adapter\Image\ImageRetriever; use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter; use PrestaShop\PrestaShop\Core\Product\ProductListingPresenter; use PrestaShop\PrestaShop\Adapter\Product\ProductColorsRetriever; use PrestaShop\PrestaShop\Core\Product\Search\ProductSearchContext; use PrestaShop\PrestaShop\Core\Product\Search\ProductSearchQuery; use PrestaShop\PrestaShop\Core\Product\Search\ProductSearchResult; use PrestaShop\PrestaShop\Core\Product\Search\SortOrder; // use PrestaShop\PrestaShop\Adapter\Search\SearchProductSearchProvider; use PrestaShop\PrestaShop\Core\Product\Search\Pagination; use PrestaShop\PrestaShop\Core\Product\Search\FacetsRendererInterface; // use LeoSearch\LeoSearchProductSearchProvider; class LeoproductsearchproductsearchModuleFrontController extends ModuleFrontController { public $php_self; public $instant_search; public $ajax_search; private $search_string; private $search_tag; private $search_cate; /** * Initialize search controller * @see FrontController::init() */ public function init() { parent::init(); $this->instant_search = Tools::getValue('instantSearch'); $this->ajax_search = Tools::getValue('ajaxSearch'); $this->search_string = Tools::getValue('q'); if (!$this->search_string) { $this->search_string = Tools::getValue('search_query'); } $this->search_tag = Tools::getValue('tag'); $this->search_cate = Tools::getValue('cate'); } /** * Assign template vars related to page content * @see FrontController::initContent() */ public function initContent() { $this->php_self = 'productsearch'; parent::initContent(); if ($this->ajax || $this->ajax_search) { $this->ajaxDie(Tools::jsonEncode($this->getAjaxProductSearchVariables())); } // $products = $this->getProducts(); $search_products = $this->getProducts(); // $search_products['products'] = $products; $this->context->smarty->assign(array( 'search_products' => $search_products, 'search_query' => $this->search_string, 'nbProducts' => $search_products['pagination']['total_items'], )); $this->setTemplate('module:leoproductsearch/views/templates/front/search.tpl'); } protected function getAjaxProductSearchVariables() { $search = $this->getProducts(); if (!$this->ajax_search) { $rendered_products_top = $this->render('catalog/_partials/products-top', array('listing' => $search)); $rendered_products = $this->render('catalog/_partials/products', array('listing' => $search)); $rendered_products_bottom = $this->render('catalog/_partials/products-bottom', array('listing' => $search)); $data = array( 'rendered_products_top' => $rendered_products_top, 'rendered_products' => $rendered_products, 'rendered_products_bottom' => $rendered_products_bottom, ); } //DONGND:: update 1.7.2.4 foreach ($search as $key => $value) { if ($key === 'products') { $value = $this->prepareProductArrayForAjaxReturn($value); } $data[$key] = $value; } return $data; } /** * Cleans the products array with only whitelisted properties. * * @return array */ protected function prepareProductArrayForAjaxReturn(array $products) { $allowed_properties = array('id_product', 'price', 'reference', 'active', 'description_short', 'link', 'link_rewrite', 'name', 'manufacturer_name', 'position', 'url', 'canonical_url', 'add_to_cart_url', 'has_discount', 'discount_type', 'discount_percentage', 'discount_percentage_absolute', 'discount_amount', 'price_amount', 'regular_price_amount', 'regular_price', 'discount_to_display', 'labels', 'main_variants', 'unit_price', 'tax_name', 'rate', 'cover' ); foreach ($products as $product_key => $product) { foreach ($product as $product_property => $data) { if (!in_array($product_property, $allowed_properties)) { unset($products[$product_key][$product_property]); } } } return $products; } protected function getProducts() { $searchProvider = new LeoSearchProductSearchProvider( $this->context->getTranslator() ); $context = new ProductSearchContext($this->context); if ($this->ajax_search && Tools::getValue('limit')) { $products_per_page = Tools::getValue('limit'); } else { $products_per_page = Configuration::get('PS_PRODUCTS_PER_PAGE'); } //DONGND:: fix to display filter default Sort by if (version_compare(_PS_VERSION_, '1.7.3.0', '>')) { $sort_oder_by = 'position'; $sort_oder_way = 'desc'; } else { $sort_oder_by = Tools::getProductsOrder('by'); $sort_oder_way = Tools::getProductsOrder('way'); } $query = new ProductSearchQuery(); $query ->setSortOrder(new SortOrder('product', $sort_oder_by, $sort_oder_way)) ->setSearchString($this->search_string) ->setSearchTag($this->search_tag) ->setResultsPerPage($products_per_page) ->setPage(max((int) Tools::getValue('page'), 1)) ; if ($this->search_cate && $this->search_cate != '') { $query->setIdCategory((int) $this->search_cate); } // set the sort order if provided in the URL if (($encodedSortOrder = Tools::getValue('order'))) { $query->setSortOrder(SortOrder::newFromString($encodedSortOrder)); } $result = $searchProvider->runQuery($context, $query); $assembler = new ProductAssembler($this->context); $presenterFactory = new ProductPresenterFactory($this->context); $presentationSettings = $presenterFactory->getPresentationSettings(); $presenter = new ProductListingPresenter(new ImageRetriever($this->context->link), $this->context->link, new PriceFormatter(), new ProductColorsRetriever(), $this->context->getTranslator()); $products_for_template = array(); foreach ($result->getProducts() as $rawProduct) { $product_temp = $presenter->present( $presentationSettings, $assembler->assembleProduct($rawProduct), $this->context->language ); # FIX 1.7.5.0 if(is_object($product_temp) && method_exists($product_temp, 'jsonSerialize')) { $product_temp = $product_temp->jsonSerialize(); } $products_for_template[] = $product_temp; } if ($this->ajax_search) { $searchVariables = array( 'products' => $products_for_template, ); return $searchVariables; } // render the facets if ($searchProvider instanceof FacetsRendererInterface) { // with the provider if it wants to $rendered_facets = $searchProvider->renderFacets($context, $result); $rendered_active_filters = $searchProvider->renderActiveFilters($context, $result); } else { // with the core $rendered_facets = $this->renderFacets($result); $rendered_active_filters = $this->renderActiveFilters($result); } $pagination = $this->getTemplateVarPagination($query, $result); $sort_orders = $this->getTemplateVarSortOrders($result->getAvailableSortOrders(), $query->getSortOrder()->toString()); $sort_selected = false; if (!empty($sort_orders)) { foreach ($sort_orders as $order) { if (isset($order['current']) && true === $order['current']) { $sort_selected = $order['label']; break; } } } $searchVariables = array( 'products' => $products_for_template, 'pagination' => $pagination, 'sort_orders' => $sort_orders, 'sort_selected' => $sort_selected, 'rendered_facets' => $rendered_facets, 'rendered_active_filters' => $rendered_active_filters, 'js_enabled' => $this->ajax, 'current_url' => $this->updateQueryString(array('q' => $result->getEncodedFacets())), ); // echo '
';
        // print_r($searchVariables);die();
        Hook::exec('actionProductSearchComplete', $searchVariables);

        return $searchVariables;
    }

    protected function getTemplateVarPagination(ProductSearchQuery $query, ProductSearchResult $result)
    {
        $pagination = new Pagination();
        $pagination
                ->setPage($query->getPage())
                ->setPagesCount(ceil($result->getTotalProductsCount() / $query->getResultsPerPage()));

        $totalItems = $result->getTotalProductsCount();
        $itemsShownFrom = ($query->getResultsPerPage() * ($query->getPage() - 1)) + 1;
        $itemsShownTo = $query->getResultsPerPage() * $query->getPage();

        return array(
            'total_items' => $totalItems,
            'items_shown_from' => $itemsShownFrom,
            'items_shown_to' => ($itemsShownTo <= $totalItems) ? $itemsShownTo : $totalItems,
            'pages' => array_map(function ($link) {
                $link['url'] = $this->updateQueryString(array(
                    'page' => $link['page'],
                ));

                return $link;
            }, $pagination->buildLinks()),
            'should_be_displayed' => (count($pagination->buildLinks()) > 3)
        );
    }

    protected function renderFacets(ProductSearchResult $result)
    {
        $facetCollection = $result->getFacetCollection();
        // not all search providers generate menus
        if (empty($facetCollection)) {
            return '';
        }

        $facetsVar = array_map(array($this, 'prepareFacetForTemplate'), $facetCollection->getFacets());

        $activeFilters = array();
        foreach ($facetsVar as $facet) {
            foreach ($facet['filters'] as $filter) {
                if ($filter['active']) {
                    $activeFilters[] = $filter;
                }
            }
        }

        return $this->render('catalog/_partials/facets', array(
            'facets' => $facetsVar,
            'js_enabled' => $this->ajax,
            'activeFilters' => $activeFilters,
            'sort_order' => $result->getCurrentSortOrder()->toString(),
            'clear_all_link' => $this->updateQueryString(array('q' => null, 'page' => null))
        ));
    }

    /**
     * Renders an array of active filters.
     *
     * @param array $facets
     *
     * @return string the HTML of the facets
     */
    protected function renderActiveFilters(ProductSearchResult $result)
    {
        $facetCollection = $result->getFacetCollection();
        // not all search providers generate menus
        if (empty($facetCollection)) {
            return '';
        }

        $facetsVar = array_map(array($this, 'prepareFacetForTemplate'), $facetCollection->getFacets());

        $activeFilters = array();
        foreach ($facetsVar as $facet) {
            foreach ($facet['filters'] as $filter) {
                if ($filter['active']) {
                    $activeFilters[] = $filter;
                }
            }
        }

        return $this->render('catalog/_partials/active_filters', array(
            'activeFilters' => $activeFilters,
            'clear_all_link' => $this->updateQueryString(array('q' => null, 'page' => null))
        ));
    }

    //DONGND:: get layout
    public function getLayout()
    {
        $entity = 'module-leoproductsearch-' . $this->php_self;

        $layout = $this->context->shop->theme->getLayoutRelativePathForPage($entity);

        if ($overridden_layout = Hook::exec('overrideLayoutTemplate', array(
            'default_layout' => $layout,
            'entity' => $entity,
            'locale' => $this->context->language->locale,
            'controller' => $this))) {
            return $overridden_layout;
        }

        if ((int) Tools::getValue('content_only')) {
            $layout = 'layouts/layout-content-only.tpl';
        }

        return $layout;
    }

    protected function getTemplateVarSortOrders(array $sortOrders, $currentSortOrderURLParameter)
    {
        return array_map(function ($sortOrder) use ($currentSortOrderURLParameter) {
            $order = $sortOrder->toArray();
            $order['current'] = $order['urlParameter'] === $currentSortOrderURLParameter;
            $order['url'] = $this->updateQueryString(array(
                'order' => $order['urlParameter'],
                'page' => null,
            ));

            return $order;
        }, $sortOrders);
    }

    //DONGND:: add breadcrumb
    public function getBreadcrumbLinks()
    {
        $breadcrumb = parent::getBreadcrumbLinks();

        $breadcrumb['links'][] = array(
            'title' => $this->l('Search', 'productsearch'),
            'url' => '',
        );

        return $breadcrumb;
    }
}