mirror of
https://github.com/bdnugget/magento2.git
synced 2026-11-07 09:17:35 +00:00
205 lines
6.6 KiB
PHP
205 lines
6.6 KiB
PHP
<?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\Exception\LocalizedException;
|
|
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
|
|
use Magento\Store\Model\Store;
|
|
use Magento\Store\Model\StoreManagerInterface;
|
|
|
|
/**
|
|
* Synonym Reader resource model
|
|
*/
|
|
class SynonymReader extends AbstractDb
|
|
{
|
|
/**
|
|
* @var \Magento\Framework\DB\Helper\Mysql\Fulltext $fullTextSelect
|
|
*/
|
|
private $fullTextSelect;
|
|
|
|
/**
|
|
* @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($phrase !== null ? 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;
|
|
}
|
|
|
|
/**
|
|
* Get all synonyms as an array
|
|
*
|
|
* @param int $storeViewId
|
|
* @return array
|
|
* @throws LocalizedException
|
|
*/
|
|
public function getAllSynonymsForStoreViewId(int $storeViewId): array
|
|
{
|
|
$connection = $this->getConnection();
|
|
|
|
$storeIdField = $connection
|
|
->quoteIdentifier(sprintf('%s.%s', $this->getMainTable(), 'store_id'));
|
|
|
|
$select = $connection
|
|
->select()
|
|
->from($this->getMainTable(), 'synonyms')
|
|
->where($storeIdField . ' IN (?)', [Store::DEFAULT_STORE_ID, $storeViewId]);
|
|
|
|
return $connection->fetchCol($select);
|
|
}
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
$phrase = $this->fullTextSelect->removeSpecialCharacters($phrase);
|
|
$matchQuery = $this->fullTextSelect->getMatchQuery(
|
|
['synonyms' => 'synonyms'],
|
|
$this->escapePhrase($phrase),
|
|
Fulltext::FULLTEXT_MODE_BOOLEAN
|
|
);
|
|
$query = $this->getConnection()->select()->from(
|
|
$this->getMainTable()
|
|
)->where($matchQuery);
|
|
|
|
return $this->getConnection()->fetchAll($query);
|
|
}
|
|
|
|
/**
|
|
* Cut trailing plus or minus sign, and @ symbol, using of which causes InnoDB to report a syntax error.
|
|
*
|
|
* @see https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html
|
|
* @param string $phrase
|
|
* @return string
|
|
*/
|
|
private function escapePhrase(string $phrase): string
|
|
{
|
|
return preg_replace('/@+|[@+-]+$|[<>]/', '', $phrase);
|
|
}
|
|
|
|
/**
|
|
* 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));
|
|
}
|
|
}
|