| Current Path : /home/rtorresani/www/vendor/magento/module-search/Model/ResourceModel/ |
| Current File : //home/rtorresani/www/vendor/magento/module-search/Model/ResourceModel/SynonymReader.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));
}
}