301 lines
9.2 KiB
PHP
Executable File
301 lines
9.2 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* @author Amasty Team
|
|
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
|
* @package Elastic Search Base for Magento 2
|
|
*/
|
|
|
|
namespace Amasty\ElasticSearch\Model;
|
|
|
|
use Amasty\ElasticSearch\Api\Data\SynonymInterface;
|
|
use Amasty\ElasticSearch\Api\SynonymRepositoryInterface;
|
|
use Amasty\ElasticSearch\Model\SynonymFactory;
|
|
use Amasty\ElasticSearch\Model\ResourceModel\Synonym as SynonymResource;
|
|
use Amasty\ElasticSearch\Model\ResourceModel\Synonym\CollectionFactory;
|
|
use Amasty\ElasticSearch\Model\ResourceModel\Synonym\Collection;
|
|
use Magento\Framework\Exception\CouldNotSaveException;
|
|
use Magento\Framework\Exception\NoSuchEntityException;
|
|
use Magento\Framework\Exception\AlreadyExistsException;
|
|
use Magento\Framework\Exception\CouldNotDeleteException;
|
|
use Magento\Framework\Api\SearchCriteriaInterface;
|
|
use Magento\Framework\Api\Search\FilterGroup;
|
|
use Magento\Ui\Api\Data\BookmarkSearchResultsInterfaceFactory;
|
|
use Magento\Framework\Api\SortOrder;
|
|
|
|
/**
|
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
|
*/
|
|
class SynonymRepository implements SynonymRepositoryInterface
|
|
{
|
|
/**
|
|
* @var BookmarkSearchResultsInterfaceFactory
|
|
*/
|
|
private $searchResultsFactory;
|
|
|
|
/**
|
|
* @var SynonymFactory
|
|
*/
|
|
private $synonymFactory;
|
|
|
|
/**
|
|
* @var SynonymResource
|
|
*/
|
|
private $synonymResource;
|
|
|
|
/**
|
|
* Model data storage
|
|
*
|
|
* @var array
|
|
*/
|
|
private $synonyms;
|
|
|
|
/**
|
|
* @var CollectionFactory
|
|
*/
|
|
private $synonymCollectionFactory;
|
|
|
|
public function __construct(
|
|
BookmarkSearchResultsInterfaceFactory $searchResultsFactory,
|
|
SynonymFactory $synonymFactory,
|
|
SynonymResource $synonymResource,
|
|
CollectionFactory $synonymCollectionFactory
|
|
) {
|
|
$this->searchResultsFactory = $searchResultsFactory;
|
|
$this->synonymFactory = $synonymFactory;
|
|
$this->synonymResource = $synonymResource;
|
|
$this->synonymCollectionFactory = $synonymCollectionFactory;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function save(SynonymInterface $synonym)
|
|
{
|
|
try {
|
|
if ($synonym->getSynonymId()) {
|
|
$synonym = $this->getById($synonym->getSynonymId())->addData($synonym->getData());
|
|
}
|
|
$this->synonymResource->save($synonym);
|
|
unset($this->synonyms[$synonym->getSynonymId()]);
|
|
} catch (AlreadyExistsException $e) {
|
|
throw new AlreadyExistsException(__($e->getMessage()));
|
|
} catch (\Exception $e) {
|
|
if ($synonym->getSynonymId()) {
|
|
throw new CouldNotSaveException(
|
|
__(
|
|
'Unable to save synonym with ID %1. Error: %2',
|
|
[$synonym->getSynonymId(), $e->getMessage()]
|
|
)
|
|
);
|
|
}
|
|
throw new CouldNotSaveException(__('Unable to save new synonym. Error: %1', $e->getMessage()));
|
|
}
|
|
|
|
return $synonym;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function getById($synonymId)
|
|
{
|
|
if (!isset($this->synonyms[$synonymId])) {
|
|
/** @var \Amasty\ElasticSearch\Model\Synonym $synonym */
|
|
$synonym = $this->synonymFactory->create();
|
|
$this->synonymResource->load($synonym, $synonymId);
|
|
if (!$synonym->getSynonymId()) {
|
|
throw new NoSuchEntityException(__('Synonym with specified ID "%1" not found.', $synonymId));
|
|
}
|
|
$this->synonyms[$synonymId] = $synonym;
|
|
}
|
|
|
|
return $this->synonyms[$synonymId];
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function delete(SynonymInterface $synonym)
|
|
{
|
|
try {
|
|
$this->synonymResource->delete($synonym);
|
|
unset($this->synonyms[$synonym->getSynonymId()]);
|
|
} catch (\Exception $e) {
|
|
if ($synonym->getSynonymId()) {
|
|
throw new CouldNotDeleteException(
|
|
__(
|
|
'Unable to remove synonym with ID %1. Error: %2',
|
|
[$synonym->getSynonymId(), $e->getMessage()]
|
|
)
|
|
);
|
|
}
|
|
throw new CouldNotDeleteException(__('Unable to remove synonym. Error: %1', $e->getMessage()));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function deleteById($synonymId)
|
|
{
|
|
$synonymModel = $this->getById($synonymId);
|
|
$this->delete($synonymModel);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function getList(SearchCriteriaInterface $searchCriteria)
|
|
{
|
|
$searchResults = $this->searchResultsFactory->create();
|
|
$searchResults->setSearchCriteria($searchCriteria);
|
|
|
|
/** @var \Amasty\ElasticSearch\Model\ResourceModel\Synonym\Collection $synonymCollection */
|
|
$synonymCollection = $this->synonymCollectionFactory->create();
|
|
// Add filters from root filter group to the collection
|
|
foreach ($searchCriteria->getFilterGroups() as $group) {
|
|
$this->addFilterGroupToCollection($group, $synonymCollection);
|
|
}
|
|
$searchResults->setTotalCount($synonymCollection->getSize());
|
|
$sortOrders = $searchCriteria->getSortOrders();
|
|
if ($sortOrders) {
|
|
$this->addOrderToCollection($sortOrders, $synonymCollection);
|
|
}
|
|
$synonymCollection->setCurPage($searchCriteria->getCurrentPage());
|
|
$synonymCollection->setPageSize($searchCriteria->getPageSize());
|
|
$synonyms = [];
|
|
/** @var SynonymInterface $synonym */
|
|
foreach ($synonymCollection->getItems() as $synonym) {
|
|
$synonyms[] = $this->getById($synonym->getId());
|
|
}
|
|
$searchResults->setItems($synonyms);
|
|
|
|
return $searchResults;
|
|
}
|
|
|
|
/**
|
|
* Helper function that adds a FilterGroup to the collection.
|
|
*
|
|
* @param FilterGroup $filterGroup
|
|
* @param Collection $synonymCollection
|
|
*
|
|
* @return void
|
|
*/
|
|
private function addFilterGroupToCollection(FilterGroup $filterGroup, Collection $synonymCollection)
|
|
{
|
|
foreach ($filterGroup->getFilters() as $filter) {
|
|
$condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq';
|
|
$synonymCollection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function that adds a SortOrder to the collection.
|
|
*
|
|
* @param SortOrder[] $sortOrders
|
|
* @param Collection $synonymCollection
|
|
*
|
|
* @return void
|
|
*/
|
|
private function addOrderToCollection($sortOrders, Collection $synonymCollection)
|
|
{
|
|
/** @var SortOrder $sortOrder */
|
|
foreach ($sortOrders as $sortOrder) {
|
|
$field = $sortOrder->getField();
|
|
$synonymCollection->addOrder(
|
|
$field,
|
|
($sortOrder->getDirection() == SortOrder::SORT_DESC) ? 'DESC' : 'ASC'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $query
|
|
* @param int $storeId
|
|
* @return array
|
|
*/
|
|
public function getSynonymsByQuery($query, $storeId)
|
|
{
|
|
$result = [];
|
|
if (!$query) {
|
|
return $result;
|
|
}
|
|
|
|
$queryArray = explode(' ', $query);
|
|
$queryArray = array_map('trim', $queryArray);
|
|
foreach ($queryArray as &$item) {
|
|
$item = str_replace(',', '', $item);
|
|
}
|
|
|
|
$queryArray = array_filter($queryArray);
|
|
if (!$queryArray) {
|
|
return $result;
|
|
}
|
|
|
|
$searchString = $this->generateSearchPattern($queryArray);
|
|
$terms = $this->getArrayTermsByConditions($searchString, $storeId);
|
|
if (!$terms) {
|
|
return $result;
|
|
}
|
|
|
|
foreach ($queryArray as $word) {
|
|
$search = $this->generateSearchPattern([$word]);
|
|
$search = '/' . $search . '/i';
|
|
$resultWord = [$word];
|
|
foreach ($terms as $term) {
|
|
if (preg_match($search, $term)) {
|
|
$term = explode(',', $term);
|
|
$term = array_map('trim', $term);
|
|
$term = array_filter($term);
|
|
// phpcs:ignore Magento2.Performance.ForeachArrayMerge.ForeachArrayMerge
|
|
$resultWord = array_merge($resultWord, $term);
|
|
}
|
|
}
|
|
$result[] = array_unique($resultWord);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param array $queryArray
|
|
* @return string
|
|
*/
|
|
private function generateSearchPattern(array $queryArray)
|
|
{
|
|
$patterns = [];
|
|
foreach ($queryArray as $word) {
|
|
$patterns[] = '^' . $word . ',';
|
|
$patterns[] = ',' . $word . ',';
|
|
$patterns[] = ',' . $word . '$';
|
|
}
|
|
|
|
$pattern = implode('|', $patterns);
|
|
|
|
return $pattern;
|
|
}
|
|
|
|
/**
|
|
* @param $searchString
|
|
* @param $storeId
|
|
* @return array
|
|
*/
|
|
private function getArrayTermsByConditions($searchString, $storeId)
|
|
{
|
|
$terms = [];
|
|
|
|
$collection = $this->synonymCollectionFactory->create()
|
|
->addFieldToFilter(SynonymInterface::STORE_ID, $storeId)
|
|
->addSearchStringFilter($searchString);
|
|
foreach ($collection as $term) {
|
|
$terms[] = $term->getTerm();
|
|
}
|
|
|
|
return $terms;
|
|
}
|
|
}
|