diff --git a/app/code/Magento/MediaGallery/Model/ResourceModel/Keyword/SaveAssetLinks.php b/app/code/Magento/MediaGallery/Model/ResourceModel/Keyword/SaveAssetLinks.php index 3437cc1c519e8..1708532569763 100644 --- a/app/code/Magento/MediaGallery/Model/ResourceModel/Keyword/SaveAssetLinks.php +++ b/app/code/Magento/MediaGallery/Model/ResourceModel/Keyword/SaveAssetLinks.php @@ -10,8 +10,10 @@ use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Adapter\Pdo\Mysql; +use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\CouldNotSaveException; use Magento\MediaGalleryApi\Api\Data\KeywordInterface; +use Magento\MediaGalleryApi\Api\GetAssetsKeywordsInterface; use Psr\Log\LoggerInterface; /** @@ -28,25 +30,33 @@ class SaveAssetLinks */ private $resourceConnection; + /** + * @var GetAssetsKeywordsInterface + */ + private $getAssetsKeywordsInterface; + /** * @var LoggerInterface */ private $logger; /** + * @param GetAssetsKeywordsInterface $getAssetsKeywordsInterface * @param ResourceConnection $resourceConnection * @param LoggerInterface $logger */ public function __construct( + GetAssetsKeywordsInterface $getAssetsKeywordsInterface, ResourceConnection $resourceConnection, LoggerInterface $logger ) { + $this->getAssetsKeywordsInterface = $getAssetsKeywordsInterface; $this->resourceConnection = $resourceConnection; $this->logger = $logger; } /** - * Save asset keywords links + * Process insert and deletion of asset keywords links * * @param int $assetId * @param KeywordInterface[] $keywordIds @@ -56,27 +66,123 @@ public function __construct( public function execute(int $assetId, array $keywordIds): void { try { - $values = []; - foreach ($keywordIds as $keywordId) { - $values[] = [$assetId, $keywordId]; + $this->deleteAssetKeywords($assetId, $keywordIds); + $this->insertAssetKeywords($assetId, $keywordIds); + } catch (\Exception $exception) { + $this->logger->critical($exception); + throw new CouldNotSaveException( + __('Could not process asset keyword links'), + $exception + ); + } + } + + /** + * Save new asset keyword links + * + * @param int $assetId + * @param array $keywordIds + * @throws CouldNotSaveException + */ + private function insertAssetKeywords(int $assetId, array $keywordIds): void + { + try { + if (!empty($keywordIds)) { + $values = []; + $keywordsToInsert = array_diff($keywordIds, $this->getCurrentKeywords($assetId)); + + foreach ($keywordsToInsert as $keywordId) { + $values[] = [$assetId, $keywordId]; + } + + if (!empty($values)) { + /** @var Mysql $connection */ + $connection = $this->resourceConnection->getConnection(); + $connection->insertArray( + $this->resourceConnection->getTableName(self::TABLE_ASSET_KEYWORD), + [self::FIELD_ASSET_ID, self::FIELD_KEYWORD_ID], + $values, + AdapterInterface::INSERT_IGNORE + ); + } } + } catch (\Exception $exception) { + $this->logger->critical($exception); + throw new CouldNotSaveException( + __('Could not save asset keyword links'), + $exception + ); + } + } - if (!empty($values)) { + /** + * Delete obsolete asset keyword links + * + * @param int $assetId + * @param array $keywords + * @throws CouldNotDeleteException + */ + private function deleteAssetKeywords(int $assetId, array $keywords): void + { + try { + $obsoleteKeywordIds = array_diff($this->getCurrentKeywords($assetId), $keywords); + + if (!empty($obsoleteKeywordIds)) { /** @var Mysql $connection */ $connection = $this->resourceConnection->getConnection(); - $connection->insertArray( - $this->resourceConnection->getTableName(self::TABLE_ASSET_KEYWORD), - [self::FIELD_ASSET_ID, self::FIELD_KEYWORD_ID], - $values, - AdapterInterface::INSERT_IGNORE + $connection->delete( + $connection->getTableName( + self::TABLE_ASSET_KEYWORD + ), + [ + self::FIELD_KEYWORD_ID . ' in (?)' => $obsoleteKeywordIds, + self::FIELD_ASSET_ID . ' = ?' => $assetId + ] ); } } catch (\Exception $exception) { $this->logger->critical($exception); - throw new CouldNotSaveException( - __('Could not save asset keyword links'), + throw new CouldNotDeleteException( + __('Could not delete obsolete asset keyword links'), $exception ); } } + + /** + * Get current keyword data of an asset + * + * @param int $assetId + * @return array + */ + private function getCurrentKeywords(int $assetId): array + { + $currentKeywordsData = $this->getAssetsKeywordsInterface->execute([$assetId]); + + if (!empty($currentKeywordsData)) { + $currentKeywords = $this->getKeywordIdsFromKeywordData( + $currentKeywordsData[$assetId]->getKeywords() + ); + + return $currentKeywords; + } + + return []; + } + + /** + * Get keyword ids from keyword data + * + * @param array $keywordsData + * @return array + */ + private function getKeywordIdsFromKeywordData(array $keywordsData): array + { + return array_map( + function (KeywordInterface $keyword): int { + return $keyword->getId(); + }, + $keywordsData + ); + } } diff --git a/app/code/Magento/MediaGallery/Model/ResourceModel/Keyword/SaveAssetsKeywords.php b/app/code/Magento/MediaGallery/Model/ResourceModel/Keyword/SaveAssetsKeywords.php index a822fafaeaa1b..a97c5f602c5c7 100644 --- a/app/code/Magento/MediaGallery/Model/ResourceModel/Keyword/SaveAssetsKeywords.php +++ b/app/code/Magento/MediaGallery/Model/ResourceModel/Keyword/SaveAssetsKeywords.php @@ -11,9 +11,7 @@ use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Adapter\Pdo\Mysql; use Magento\Framework\Exception\CouldNotSaveException; -use Magento\Framework\Exception\CouldNotDeleteException; use Magento\MediaGalleryApi\Api\Data\KeywordInterface; -use Magento\MediaGalleryApi\Api\GetAssetsKeywordsInterface; use Magento\MediaGalleryApi\Api\SaveAssetsKeywordsInterface; use Psr\Log\LoggerInterface; @@ -23,7 +21,6 @@ class SaveAssetsKeywords implements SaveAssetsKeywordsInterface { private const TABLE_KEYWORD = 'media_gallery_keyword'; - private const TABLE_ASSET_KEYWORD = 'media_gallery_asset_keyword'; private const ID = 'id'; private const KEYWORD = 'keyword'; @@ -37,11 +34,6 @@ class SaveAssetsKeywords implements SaveAssetsKeywordsInterface */ private $saveAssetLinks; - /** - * @var GetAssetsKeywordsInterface - */ - private $getAssetsKeywordsInterface; - /** * @var LoggerInterface */ @@ -52,18 +44,15 @@ class SaveAssetsKeywords implements SaveAssetsKeywordsInterface * * @param ResourceConnection $resourceConnection * @param SaveAssetLinks $saveAssetLinks - * @param GetAssetsKeywordsInterface $getAssetsKeywordsInterface * @param LoggerInterface $logger */ public function __construct( ResourceConnection $resourceConnection, SaveAssetLinks $saveAssetLinks, - GetAssetsKeywordsInterface $getAssetsKeywordsInterface, LoggerInterface $logger ) { $this->resourceConnection = $resourceConnection; $this->saveAssetLinks = $saveAssetLinks; - $this->getAssetsKeywordsInterface = $getAssetsKeywordsInterface; $this->logger = $logger; } @@ -94,7 +83,6 @@ public function execute(array $assetKeywords): void * * @param KeywordInterface[] $keywords * @param int $assetId - * @throws CouldNotDeleteException * @throws CouldNotSaveException * @throws \Zend_Db_Exception */ @@ -109,8 +97,6 @@ private function saveAssetKeywords(array $keywords, int $assetId): void return; } - $this->deleteObsoleteAssetKeywords($data, $assetId); - /** @var Mysql $connection */ $connection = $this->resourceConnection->getConnection(); $connection->insertArray( @@ -139,58 +125,4 @@ private function getKeywordIds(array $keywords): array return $connection->fetchCol($select); } - - /** - * Deletes obsolete asset keywords links - * - * @param array $newKeywords - * @param int $assetId - * @throws CouldNotDeleteException - */ - private function deleteObsoleteAssetKeywords(array $newKeywords, int $assetId): void - { - $oldKeywordData = $this->getAssetsKeywordsInterface->execute([$assetId]); - - if (empty($newKeywords) || empty($oldKeywordData)) { - return; - } - - $oldKeywordData = $this->getAssetsKeywordsInterface->execute([$assetId]); - $oldKeywords = $oldKeywordData[$assetId]->getKeywords(); - - foreach ($oldKeywords as $oldKeyword) { - if (!in_array($oldKeyword->getKeyword(), $newKeywords)) { - $obsoleteKeywords[] = $oldKeyword->getKeyword(); - } - } - - if (empty($obsoleteKeywords)) { - return; - } - - $obsoleteKeywordIds = $this->getKeywordIds($obsoleteKeywords); - - try { - /** @var Mysql $connection */ - $connection = $this->resourceConnection->getConnection(); - $connection->delete( - $connection->getTableName( - self::TABLE_ASSET_KEYWORD - ), - [ - 'keyword_id in (?)' => $obsoleteKeywordIds, - 'asset_id = ?' => $assetId - ] - ); - } catch (\Exception $exception) { - $this->logger->critical($exception); - $failedAssetId = $assetId; - } - - if (!empty($failedAssetId)) { - throw new CouldNotDeleteException( - __('Could not delete obsolete keyword relation for asset id: %id', ['id' => $assetId]) - ); - } - } }