SynonymReader.php 5.45 KB
Newer Older
Ketan's avatar
Ketan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Magento\Search\Model\ResourceModel;

use Magento\Framework\DB\Helper\Mysql\Fulltext;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
use Magento\Store\Model\StoreManagerInterface;

/**
 * Synonym Reader resource model
 */
class SynonymReader extends AbstractDb
{
    /**
     * @var \Magento\Framework\DB\Helper\Mysql\Fulltext $fullTextSelect
     */
    private $fullTextSelect;

    /**
     * Store manager
     *
     * @var StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\DB\Helper\Mysql\Fulltext $fulltext
     * @param string $connectionName
     */
    public function __construct(
        \Magento\Framework\Model\ResourceModel\Db\Context $context,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\DB\Helper\Mysql\Fulltext $fulltext,
        $connectionName = null
    ) {
        parent::__construct($context, $connectionName);
        $this->fullTextSelect = $fulltext;
        $this->storeManager = $storeManager;
    }

    /**
     * Custom load model: Get data by user query phrase
     *
     * @param \Magento\Search\Model\SynonymReader $object
     * @param string $phrase
     * @return $this
     */
    public function loadByPhrase(\Magento\Search\Model\SynonymReader $object, $phrase)
    {
        $rows = $this->queryByPhrase(strtolower($phrase));
        $synsPerScope = $this->getSynRowsPerScope($rows);

        if (!empty($synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_STORES])) {
            $object->setData($synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_STORES]);
        } elseif (!empty($synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES])) {
            $object->setData($synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES]);
        } else {
            $object->setData($synsPerScope[\Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT]);
        }
        $this->_afterLoad($object);
        return $this;
    }

    /**
     * Init resource data
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('search_synonyms', 'group_id');
    }

    /**
     * A helper function to query by phrase and get results
     *
     * @param string $phrase
     * @return array
     */
    private function queryByPhrase($phrase)
    {
        $matchQuery = $this->fullTextSelect->getMatchQuery(
            ['synonyms' => 'synonyms'],
            $phrase,
            Fulltext::FULLTEXT_MODE_BOOLEAN
        );
        $query = $this->getConnection()->select()->from(
            $this->getMainTable()
        )->where($matchQuery);

        return $this->getConnection()->fetchAll($query);
    }

    /**
     * A private helper function to retrieve matching synonym groups per scope
     *
     * @param array $rows
     * @return array
     */
    private function getSynRowsPerScope($rows)
    {
        $synRowsForStoreView = [];
        $synRowsForWebsite = [];
        $synRowsForDefault = [];

        // The synonyms configured for current store view gets highest priority. Second highest is current website
        // scope. If there were no store view and website specific synonyms then at last 'default' (All store views)
        // will be considered.
        foreach ($rows as $row) {
            if ($this->isSynRowForStoreView($row)) {
                // Check for current store view
                $synRowsForStoreView[] = $row;
            } elseif (empty($synRowsForStoreView) && $this->isSynRowForWebsite($row)) {
                // Check for current website
                $synRowsForWebsite[] = $row;
            } elseif (empty($synRowsForStoreView)
                && empty($synRowsForWebsite)
                && $this->isSynRowForDefaultScope($row)) {
                // Check for all store views (i.e. global/default config)
                $synRowsForDefault[] = $row;
            }
        }
        $synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_STORES] = $synRowsForStoreView;
        $synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES] = $synRowsForWebsite;
        $synsPerScope[\Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT] = $synRowsForDefault;
        return $synsPerScope;
    }

    /**
     * A helper method to check if the synonym group row is for the current store view
     *
     * @param array $row
     * @return bool
     */
    private function isSynRowForStoreView($row)
    {
        $storeViewId = $this->storeManager->getStore()->getId();
        return ($row['store_id'] === $storeViewId);
    }

    /**
     * A helper method to check if the synonym group row is for the current website
     *
     * @param array $row
     * @return bool
     */
    private function isSynRowForWebsite($row)
    {
        $websiteId = $this->storeManager->getStore()->getWebsiteId();
        return (($row['website_id'] === $websiteId) && ($row['store_id'] == 0));
    }

    /**
     * A helper method to check if the synonym group row is for all store views (default or global scope)
     *
     * @param array $row
     * @return bool
     */
    private function isSynRowForDefaultScope($row)
    {
        return (($row['website_id'] == 0) && ($row['store_id'] == 0));
    }
}