123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Search\Model;
- use Magento\Framework\Exception\CouldNotDeleteException;
- use Magento\Search\Api\Data\SynonymGroupInterface;
- use Magento\Search\Api\SynonymGroupRepositoryInterface;
- use Magento\Search\Model\ResourceModel\SynonymGroup as SynonymGroupResourceModel;
- /**
- * Synonym Group repository, provides implementation of saving and deleting synonym groups
- */
- class SynonymGroupRepository implements SynonymGroupRepositoryInterface
- {
- /**
- * SynonymGroup Factory
- *
- * @var SynonymGroupFactory
- */
- protected $synonymGroupFactory;
- /**
- * SynonymGroup resource model
- *
- * @var SynonymGroupResourceModel
- */
- protected $resourceModel;
- /**
- * Constructor
- *
- * @param SynonymGroupFactory $synonymGroupFactory
- * @param SynonymGroupResourceModel $resourceModel
- */
- public function __construct(
- \Magento\Search\Model\SynonymGroupFactory $synonymGroupFactory,
- SynonymGroupResourceModel $resourceModel
- ) {
- $this->synonymGroupFactory = $synonymGroupFactory;
- $this->resourceModel = $resourceModel;
- }
- /**
- * @inheritdoc
- */
- public function save(SynonymGroupInterface $synonymGroup, $errorOnMergeConflict = false)
- {
- /** @var SynonymGroup $synonymGroupModel */
- $synonymGroupModel = $this->synonymGroupFactory->create();
- $synonymGroupModel->load($synonymGroup->getGroupId());
- $isCreate = $synonymGroupModel->getSynonymGroup() === null;
- if ($isCreate) {
- return $this->create($synonymGroup, $errorOnMergeConflict);
- } else {
- return $this->update($synonymGroupModel, $synonymGroup, $errorOnMergeConflict);
- }
- }
- /**
- * Deletes a synonym group
- *
- * @param SynonymGroupInterface $synonymGroup
- * @throws CouldNotDeleteException
- * @return bool
- */
- public function delete(SynonymGroupInterface $synonymGroup)
- {
- try {
- $this->resourceModel->delete($synonymGroup);
- } catch (\Exception $exception) {
- throw new CouldNotDeleteException(
- __(
- 'The synonym group with the "%1" ID can\'t be deleted. %2',
- $synonymGroup->getGroupId(),
- $exception->getMessage()
- )
- );
- }
- return true;
- }
- /**
- * Return a particular synonym group interface instance based on passed in synonym group id
- *
- * @param int $synonymGroupId
- * @return \Magento\Search\Api\Data\SynonymGroupInterface
- */
- public function get($synonymGroupId)
- {
- /** @var SynonymGroup $synonymGroup */
- $synonymGroup = $this->synonymGroupFactory->create();
- if ($synonymGroupId !== null) {
- $synonymGroup->load($synonymGroupId);
- }
- return $synonymGroup;
- }
- /**
- * Private helper to create a synonym group, throw exception on merge conflict
- *
- * @param SynonymGroupInterface $synonymGroup
- * @param bool $errorOnMergeConflict
- * @return SynonymGroupInterface
- * @throws Synonym\MergeConflictException
- * @throws \Magento\Framework\Exception\AlreadyExistsException
- */
- private function create(SynonymGroupInterface $synonymGroup, $errorOnMergeConflict)
- {
- $matchingSynonymGroups = $this->getMatchingSynonymGroups($synonymGroup);
- if ($matchingSynonymGroups) {
- if ($errorOnMergeConflict) {
- throw new Synonym\MergeConflictException(
- $this->parseToArray($matchingSynonymGroups),
- $this->getExceptionMessage($matchingSynonymGroups)
- );
- }
- // merge matching synonyms before creating a new row
- $mergedSynonyms = $this->merge($synonymGroup, array_keys($matchingSynonymGroups));
- /** @var SynonymGroup $newSynonymGroupModel */
- $newSynonymGroupModel = $this->synonymGroupFactory->create();
- $newSynonymGroupModel->setSynonymGroup(implode(',', $mergedSynonyms));
- $newSynonymGroupModel->setWebsiteId($synonymGroup->getWebsiteId());
- $newSynonymGroupModel->setStoreId($synonymGroup->getStoreId());
- $this->resourceModel->save($newSynonymGroupModel);
- $synonymGroup->setSynonymGroup($newSynonymGroupModel->getSynonymGroup());
- $synonymGroup->setGroupId($newSynonymGroupModel->getGroupId());
- } else {
- // no merge conflict, perform simple insert
- /** @var SynonymGroup $synonymGroupModel */
- $synonymGroupModel = $this->synonymGroupFactory->create();
- $this->populateSynonymGroupModel($synonymGroupModel, $synonymGroup);
- $this->resourceModel->save($synonymGroupModel);
- $synonymGroup->setGroupId($synonymGroupModel->getGroupId());
- }
- return $synonymGroup;
- }
- /**
- * Perform synonyms merge
- *
- * @param SynonymGroupInterface $synonymGroupToMerge
- * @param array $matchingGroupIds
- * @return array
- * @throws \Exception
- */
- private function merge(SynonymGroupInterface $synonymGroupToMerge, array $matchingGroupIds)
- {
- $mergedSynonyms = [];
- foreach ($matchingGroupIds as $groupId) {
- /** @var SynonymGroup $synonymGroupModel */
- $synonymGroupModel = $this->synonymGroupFactory->create();
- $synonymGroupModel->load($groupId);
- $mergedSynonyms = array_merge($mergedSynonyms, explode(',', $synonymGroupModel->getSynonymGroup()));
- $synonymGroupModel->delete();
- }
- $mergedSynonyms = array_merge($mergedSynonyms, explode(',', $synonymGroupToMerge->getSynonymGroup()));
- $mergedSynonyms = array_unique($mergedSynonyms);
- return $mergedSynonyms;
- }
- /**
- * Private helper to populate SynonymGroup model with data
- *
- * @param SynonymGroup $modelToPopulate
- * @param SynonymGroupInterface $synonymGroupData
- * @return void
- */
- private function populateSynonymGroupModel(SynonymGroup $modelToPopulate, SynonymGroupInterface $synonymGroupData)
- {
- $modelToPopulate->setWebsiteId($synonymGroupData->getWebsiteId());
- $modelToPopulate->setStoreId($synonymGroupData->getStoreId());
- $modelToPopulate->setSynonymGroup($synonymGroupData->getSynonymGroup());
- }
- /**
- * Private helper to update a synonym group, throw exception on merge conflict
- *
- * @param SynonymGroup $oldSynonymGroup
- * @param SynonymGroupInterface $newSynonymGroup
- * @param bool $errorOnMergeConflict
- * @return SynonymGroupInterface
- * @throws Synonym\MergeConflictException
- * @throws \Magento\Framework\Exception\AlreadyExistsException
- */
- private function update(
- SynonymGroup $oldSynonymGroup,
- SynonymGroupInterface $newSynonymGroup,
- $errorOnMergeConflict
- ) {
- $matchingSynonymGroups = $this->getMatchingSynonymGroups($newSynonymGroup);
- // ignore existing synonym group as it's value will be discarded
- $matchingSynonymGroups = array_diff_key(
- $matchingSynonymGroups,
- [$oldSynonymGroup->getGroupId() => $oldSynonymGroup->getSynonymGroup()]
- );
- if ($matchingSynonymGroups) {
- if ($errorOnMergeConflict) {
- throw new Synonym\MergeConflictException(
- $this->parseToArray($matchingSynonymGroups),
- $this->getExceptionMessage($matchingSynonymGroups)
- );
- }
- // merge matching synonyms before updating a row
- $mergedSynonyms = $this->merge($newSynonymGroup, array_keys($matchingSynonymGroups));
- $oldSynonymGroup->setSynonymGroup(implode(',', $mergedSynonyms));
- $oldSynonymGroup->setWebsiteId($newSynonymGroup->getWebsiteId());
- $oldSynonymGroup->setStoreId($newSynonymGroup->getStoreId());
- $this->resourceModel->save($oldSynonymGroup);
- } else {
- // no merge conflict, perform simple update
- $this->populateSynonymGroupModel($oldSynonymGroup, $newSynonymGroup);
- $this->resourceModel->save($oldSynonymGroup);
- }
- return $oldSynonymGroup;
- }
- /**
- * Gets merge conflict exception message
- *
- * @param string[] $matchingSynonymGroups
- * @return \Magento\Framework\Phrase
- */
- private function getExceptionMessage($matchingSynonymGroups)
- {
- $displayString = '(';
- $displayString .= implode('), (', $matchingSynonymGroups);
- $displayString .= ')';
- return __('Merge conflict with existing synonym group(s): %1', $displayString);
- }
- /**
- * Parse the matching synonym groups into array
- *
- * @param string[] $matchingSynonymGroups
- * @return array
- */
- private function parseToArray($matchingSynonymGroups)
- {
- $parsedArray = [];
- foreach ($matchingSynonymGroups as $matchingSynonymGroup) {
- $parsedArray[] = explode(',', $matchingSynonymGroup);
- }
- return $parsedArray;
- }
- /**
- * Gets all other matching synonym groups in the same scope
- *
- * @param SynonymGroupInterface $synonymGroup
- * @return string[]
- */
- private function getMatchingSynonymGroups(SynonymGroupInterface $synonymGroup)
- {
- $synonymGroupsInScope = $this->resourceModel->getByScope(
- $synonymGroup->getWebsiteId(),
- $synonymGroup->getStoreId()
- );
- $matchingSynonymGroups = [];
- foreach ($synonymGroupsInScope as $synonymGroupInScope) {
- if (array_intersect(
- explode(',', $synonymGroup->getSynonymGroup()),
- explode(',', $synonymGroupInScope['synonyms'])
- )) {
- $matchingSynonymGroups[$synonymGroupInScope['group_id']] = $synonymGroupInScope['synonyms'];
- }
- }
- return $matchingSynonymGroups;
- }
- }
|