|
11 | 11 | use Magento\Catalog\Model\Product\Visibility;
|
12 | 12 | use Magento\Catalog\Model\ResourceModel\Product\Link;
|
13 | 13 | use Magento\CatalogImportExport\Model\Import\Product\ImageTypeProcessor;
|
| 14 | +use Magento\CatalogImportExport\Model\Import\Product\LinkProcessor; |
14 | 15 | use Magento\CatalogImportExport\Model\Import\Product\MediaGalleryProcessor;
|
15 | 16 | use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface as ValidatorInterface;
|
16 | 17 | use Magento\CatalogImportExport\Model\StockItemImporterInterface;
|
@@ -742,6 +743,11 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
|
742 | 743 | */
|
743 | 744 | private $productRepository;
|
744 | 745 |
|
| 746 | + /** |
| 747 | + * @var LinkProcessor |
| 748 | + */ |
| 749 | + private $linkProcessor; |
| 750 | + |
745 | 751 | /**
|
746 | 752 | * @param \Magento\Framework\Json\Helper\Data $jsonHelper
|
747 | 753 | * @param \Magento\ImportExport\Helper\Data $importExportData
|
@@ -787,6 +793,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
|
787 | 793 | * @param StockItemImporterInterface|null $stockItemImporter
|
788 | 794 | * @param DateTimeFactory $dateTimeFactory
|
789 | 795 | * @param ProductRepositoryInterface|null $productRepository
|
| 796 | + * @oaram LinkProcessor|null $linkProcessor |
790 | 797 | * @throws LocalizedException
|
791 | 798 | * @throws \Magento\Framework\Exception\FileSystemException
|
792 | 799 | * @SuppressWarnings(PHPMD.ExcessiveParameterList)
|
@@ -836,7 +843,8 @@ public function __construct(
|
836 | 843 | MediaGalleryProcessor $mediaProcessor = null,
|
837 | 844 | StockItemImporterInterface $stockItemImporter = null,
|
838 | 845 | DateTimeFactory $dateTimeFactory = null,
|
839 |
| - ProductRepositoryInterface $productRepository = null |
| 846 | + ProductRepositoryInterface $productRepository = null, |
| 847 | + LinkProcessor $linkProcessor = null |
840 | 848 | ) {
|
841 | 849 | $this->_eventManager = $eventManager;
|
842 | 850 | $this->stockRegistry = $stockRegistry;
|
@@ -872,6 +880,8 @@ public function __construct(
|
872 | 880 | $this->mediaProcessor = $mediaProcessor ?: ObjectManager::getInstance()->get(MediaGalleryProcessor::class);
|
873 | 881 | $this->stockItemImporter = $stockItemImporter ?: ObjectManager::getInstance()
|
874 | 882 | ->get(StockItemImporterInterface::class);
|
| 883 | + $this->linkProcessor = $linkProcessor ?? ObjectManager::getInstance() |
| 884 | + ->get(LinkProcessor::class); |
875 | 885 | parent::__construct(
|
876 | 886 | $jsonHelper,
|
877 | 887 | $importExportData,
|
@@ -1248,30 +1258,13 @@ protected function _prepareRowForDb(array $rowData)
|
1248 | 1258 | *
|
1249 | 1259 | * Must be called after ALL products saving done.
|
1250 | 1260 | *
|
| 1261 | + * @deprecated use linkProcessor Directly |
| 1262 | + * |
1251 | 1263 | * @return $this
|
1252 | 1264 | */
|
1253 | 1265 | protected function _saveLinks()
|
1254 | 1266 | {
|
1255 |
| - /** @var Link $resource */ |
1256 |
| - $resource = $this->_linkFactory->create(); |
1257 |
| - $mainTable = $resource->getMainTable(); |
1258 |
| - $positionAttrId = []; |
1259 |
| - $nextLinkId = $this->_resourceHelper->getNextAutoincrement($mainTable); |
1260 |
| - |
1261 |
| - // pre-load 'position' attributes ID for each link type once |
1262 |
| - foreach ($this->_linkNameToId as $linkId) { |
1263 |
| - $select = $this->_connection->select()->from( |
1264 |
| - $resource->getTable('catalog_product_link_attribute'), |
1265 |
| - ['id' => 'product_link_attribute_id'] |
1266 |
| - )->where( |
1267 |
| - 'link_type_id = :link_id AND product_link_attribute_code = :position' |
1268 |
| - ); |
1269 |
| - $bind = [':link_id' => $linkId, ':position' => 'position']; |
1270 |
| - $positionAttrId[$linkId] = $this->_connection->fetchOne($select, $bind); |
1271 |
| - } |
1272 |
| - while ($bunch = $this->_dataSourceModel->getNextBunch()) { |
1273 |
| - $this->processLinkBunches($bunch, $resource, $nextLinkId, $positionAttrId); |
1274 |
| - } |
| 1267 | + $this->linkProcessor->saveLinks($this, $this->_dataSourceModel, $this->getProductEntityLinkField()); |
1275 | 1268 | return $this;
|
1276 | 1269 | }
|
1277 | 1270 |
|
@@ -3034,167 +3027,4 @@ private function getValidationErrorLevel($sku): string
|
3034 | 3027 | ? ProcessingError::ERROR_LEVEL_CRITICAL
|
3035 | 3028 | : ProcessingError::ERROR_LEVEL_NOT_CRITICAL;
|
3036 | 3029 | }
|
3037 |
| - |
3038 |
| - /** |
3039 |
| - * Processes link bunches |
3040 |
| - * |
3041 |
| - * @param array $bunch |
3042 |
| - * @param Link $resource |
3043 |
| - * @param int $nextLinkId |
3044 |
| - * @param array $positionAttrId |
3045 |
| - * @return void |
3046 |
| - */ |
3047 |
| - private function processLinkBunches( |
3048 |
| - array $bunch, |
3049 |
| - Link $resource, |
3050 |
| - int $nextLinkId, |
3051 |
| - array $positionAttrId |
3052 |
| - ): void { |
3053 |
| - $productIds = []; |
3054 |
| - $linkRows = []; |
3055 |
| - $positionRows = []; |
3056 |
| - |
3057 |
| - $bunch = array_filter($bunch, [$this, 'isRowAllowedToImport'], ARRAY_FILTER_USE_BOTH); |
3058 |
| - foreach ($bunch as $rowData) { |
3059 |
| - $sku = $rowData[self::COL_SKU]; |
3060 |
| - $productId = $this->skuProcessor->getNewSku($sku)[$this->getProductEntityLinkField()]; |
3061 |
| - $productIds[] = $productId; |
3062 |
| - $productLinkKeys = $this->fetchProductLinks($resource, $productId); |
3063 |
| - $linkNameToId = array_filter( |
3064 |
| - $this->_linkNameToId, |
3065 |
| - function ($linkName) use ($rowData) { |
3066 |
| - return isset($rowData[$linkName . 'sku']); |
3067 |
| - }, |
3068 |
| - ARRAY_FILTER_USE_KEY |
3069 |
| - ); |
3070 |
| - foreach ($linkNameToId as $linkName => $linkId) { |
3071 |
| - $linkSkus = explode($this->getMultipleValueSeparator(), $rowData[$linkName . 'sku']); |
3072 |
| - $linkPositions = !empty($rowData[$linkName . 'position']) |
3073 |
| - ? explode($this->getMultipleValueSeparator(), $rowData[$linkName . 'position']) |
3074 |
| - : []; |
3075 |
| - |
3076 |
| - $linkSkus = array_filter( |
3077 |
| - $linkSkus, |
3078 |
| - function ($linkedSku) use ($sku) { |
3079 |
| - $linkedSku = trim($linkedSku); |
3080 |
| - return ($this->skuProcessor->getNewSku($linkedSku) !== null || $this->isSkuExist($linkedSku)) |
3081 |
| - && strcasecmp($linkedSku, $sku) !== 0; |
3082 |
| - } |
3083 |
| - ); |
3084 |
| - foreach ($linkSkus as $linkedKey => $linkedSku) { |
3085 |
| - $linkedId = $this->getProductLinkedId($linkedSku); |
3086 |
| - if ($linkedId == null) { |
3087 |
| - // Import file links to a SKU which is skipped for some reason, which leads to a "NULL" |
3088 |
| - // link causing fatal errors. |
3089 |
| - $formatStr = 'WARNING: Orphaned link skipped: From SKU %s (ID %d) to SKU %s, Link type id: %d'; |
3090 |
| - $exception = new \Exception(sprintf($formatStr, $sku, $productId, $linkedSku, $linkId)); |
3091 |
| - $this->_logger->critical($exception); |
3092 |
| - continue; |
3093 |
| - } |
3094 |
| - $linkKey = $this->composeLinkKey($productId, $linkedId, $linkId); |
3095 |
| - $productLinkKeys[$linkKey] = $productLinkKeys[$linkKey] ?? $nextLinkId; |
3096 |
| - |
3097 |
| - $linkRows[$linkKey] = $linkRows[$linkKey] ?? [ |
3098 |
| - 'link_id' => $productLinkKeys[$linkKey], |
3099 |
| - 'product_id' => $productId, |
3100 |
| - 'linked_product_id' => $linkedId, |
3101 |
| - 'link_type_id' => $linkId, |
3102 |
| - ]; |
3103 |
| - |
3104 |
| - if (!empty($linkPositions[$linkedKey])) { |
3105 |
| - $positionRows[] = [ |
3106 |
| - 'link_id' => $productLinkKeys[$linkKey], |
3107 |
| - 'product_link_attribute_id' => $positionAttrId[$linkId], |
3108 |
| - 'value' => $linkPositions[$linkedKey], |
3109 |
| - ]; |
3110 |
| - } |
3111 |
| - $nextLinkId++; |
3112 |
| - } |
3113 |
| - } |
3114 |
| - } |
3115 |
| - $this->saveLinksData($resource, $productIds, $linkRows, $positionRows); |
3116 |
| - } |
3117 |
| - |
3118 |
| - /** |
3119 |
| - * Fetches Product Links |
3120 |
| - * |
3121 |
| - * @param Link $resource |
3122 |
| - * @param int $productId |
3123 |
| - * @return array |
3124 |
| - */ |
3125 |
| - private function fetchProductLinks(Link $resource, int $productId) : array |
3126 |
| - { |
3127 |
| - $productLinkKeys = []; |
3128 |
| - $select = $this->_connection->select()->from( |
3129 |
| - $resource->getTable('catalog_product_link'), |
3130 |
| - ['id' => 'link_id', 'linked_id' => 'linked_product_id', 'link_type_id' => 'link_type_id'] |
3131 |
| - )->where( |
3132 |
| - 'product_id = :product_id' |
3133 |
| - ); |
3134 |
| - $bind = [':product_id' => $productId]; |
3135 |
| - foreach ($this->_connection->fetchAll($select, $bind) as $linkData) { |
3136 |
| - $linkKey = $this->composeLinkKey($productId, $linkData['linked_id'], $linkData['link_type_id']); |
3137 |
| - $productLinkKeys[$linkKey] = $linkData['id']; |
3138 |
| - } |
3139 |
| - |
3140 |
| - return $productLinkKeys; |
3141 |
| - } |
3142 |
| - |
3143 |
| - /** |
3144 |
| - * Gets the Id of the Sku |
3145 |
| - * |
3146 |
| - * @param string $linkedSku |
3147 |
| - * @return int|null |
3148 |
| - */ |
3149 |
| - private function getProductLinkedId(string $linkedSku) : ?int |
3150 |
| - { |
3151 |
| - $linkedSku = trim($linkedSku); |
3152 |
| - $newSku = $this->skuProcessor->getNewSku($linkedSku); |
3153 |
| - $linkedId = !empty($newSku) ? $newSku['entity_id'] : $this->getExistingSku($linkedSku)['entity_id']; |
3154 |
| - return $linkedId; |
3155 |
| - } |
3156 |
| - |
3157 |
| - /** |
3158 |
| - * Saves information about product links |
3159 |
| - * |
3160 |
| - * @param Link $resource |
3161 |
| - * @param array $productIds |
3162 |
| - * @param array $linkRows |
3163 |
| - * @param array $positionRows |
3164 |
| - * @throws LocalizedException |
3165 |
| - */ |
3166 |
| - private function saveLinksData(Link $resource, array $productIds, array $linkRows, array $positionRows) |
3167 |
| - { |
3168 |
| - $mainTable = $resource->getMainTable(); |
3169 |
| - if (Import::BEHAVIOR_APPEND != $this->getBehavior() && $productIds) { |
3170 |
| - $this->_connection->delete( |
3171 |
| - $mainTable, |
3172 |
| - $this->_connection->quoteInto('product_id IN (?)', array_unique($productIds)) |
3173 |
| - ); |
3174 |
| - } |
3175 |
| - if ($linkRows) { |
3176 |
| - $this->_connection->insertOnDuplicate($mainTable, $linkRows, ['link_id']); |
3177 |
| - } |
3178 |
| - if ($positionRows) { |
3179 |
| - // process linked product positions |
3180 |
| - $this->_connection->insertOnDuplicate( |
3181 |
| - $resource->getAttributeTypeTable('int'), |
3182 |
| - $positionRows, |
3183 |
| - ['value'] |
3184 |
| - ); |
3185 |
| - } |
3186 |
| - } |
3187 |
| - |
3188 |
| - /** |
3189 |
| - * Composes the link key |
3190 |
| - * |
3191 |
| - * @param int $productId |
3192 |
| - * @param int $linkedId |
3193 |
| - * @param int $linkTypeId |
3194 |
| - * @return string |
3195 |
| - */ |
3196 |
| - private function composeLinkKey(int $productId, int $linkedId, int $linkTypeId) : string |
3197 |
| - { |
3198 |
| - return "{$productId}-{$linkedId}-{$linkTypeId}"; |
3199 |
| - } |
3200 | 3030 | }
|
0 commit comments