Files

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;
}
}