/** * Update attribute values for entity list per store * * @param array $entityIds * @param array $attrData * @param int $storeId * @return $this * @throws \Exception */ public function updateAttributes($entityIds, $attrData, $storeId) { $object = new \Magento\Framework\DataObject(); $object->setStoreId($storeId); $this->getConnection()->beginTransaction(); try { foreach ($attrData as $attrCode => $value) { $attribute = $this->getAttribute($attrCode); if (!$attribute->getAttributeId()) { continue; } $i = 0; foreach ($entityIds as $entityId) { $i++; $object->setId($entityId); $object->setEntityId($entityId); // collect data for save $this->_saveAttributeValue($object, $attribute, $value); // save collected data every 1000 rows if ($i % 1000 == 0) { $this->_processAttributeValues(); } } $this->_processAttributeValues(); } $this->getConnection()->commit(); } catch (\Exception $e) { $this->getConnection()->rollBack(); throw $e; } return $this; }
/** * After Save Attribute manipulation * * @param \Magento\Catalog\Model\Product $object * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function afterSave($object) { $websiteId = $this->_storeManager->getStore($object->getStoreId())->getWebsiteId(); $isGlobal = $this->getAttribute()->isScopeGlobal() || $websiteId == 0; $priceRows = $object->getData($this->getAttribute()->getName()); if ($priceRows === null) { return $this; } $old = []; $new = []; // prepare original data for compare $origPrices = $object->getOrigData($this->getAttribute()->getName()); if (!is_array($origPrices)) { $origPrices = []; } foreach ($origPrices as $data) { if ($data['website_id'] > 0 || $data['website_id'] == '0' && $isGlobal) { $key = join('-', array_merge([$data['website_id'], $data['cust_group']], $this->_getAdditionalUniqueFields($data))); $old[$key] = $data; } } // prepare data for save foreach ($priceRows as $data) { $hasEmptyData = false; foreach ($this->_getAdditionalUniqueFields($data) as $field) { if (empty($field)) { $hasEmptyData = true; break; } } if ($hasEmptyData || !isset($data['cust_group']) || !empty($data['delete'])) { continue; } if ($this->getAttribute()->isScopeGlobal() && $data['website_id'] > 0) { continue; } if (!$isGlobal && (int) $data['website_id'] == 0) { continue; } $key = join('-', array_merge([$data['website_id'], $data['cust_group']], $this->_getAdditionalUniqueFields($data))); $useForAllGroups = $data['cust_group'] == $this->_groupManagement->getAllCustomersGroup()->getId(); $customerGroupId = !$useForAllGroups ? $data['cust_group'] : 0; $new[$key] = array_merge(['website_id' => $data['website_id'], 'all_groups' => $useForAllGroups ? 1 : 0, 'customer_group_id' => $customerGroupId, 'value' => $data['price']], $this->_getAdditionalUniqueFields($data)); } $delete = array_diff_key($old, $new); $insert = array_diff_key($new, $old); $update = array_intersect_key($new, $old); $isChanged = false; $productId = $object->getId(); if (!empty($delete)) { foreach ($delete as $data) { $this->_getResource()->deletePriceData($productId, null, $data['price_id']); $isChanged = true; } } if (!empty($insert)) { foreach ($insert as $data) { $price = new \Magento\Framework\DataObject($data); $price->setEntityId($productId); $this->_getResource()->savePriceData($price); $isChanged = true; } } if (!empty($update)) { foreach ($update as $k => $v) { if ($old[$k]['price'] != $v['value']) { $price = new \Magento\Framework\DataObject(['value_id' => $old[$k]['price_id'], 'value' => $v['value']]); $this->_getResource()->savePriceData($price); $isChanged = true; } } } if ($isChanged) { $valueChangedKey = $this->getAttribute()->getName() . '_changed'; $object->setData($valueChangedKey, 1); } return $this; }
/** * Retrieve Product data objects * * @param int|array $productIds * @param int $storeId * @param int $entityId * @param int &$lastEntityId * @return array */ protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId) { $products = []; $websiteId = $this->_storeManager->getStore($storeId)->getWebsiteId(); $connection = $this->getConnection(); if ($productIds !== null) { if (!is_array($productIds)) { $productIds = [$productIds]; } } $bind = ['website_id' => (int) $websiteId, 'entity_id' => (int) $entityId]; $select = $connection->select()->useStraightJoin(true)->from(['e' => $this->getTable('catalog_product_entity')], ['entity_id'])->join(['w' => $this->getTable('catalog_product_website')], 'e.entity_id = w.product_id AND w.website_id = :website_id', [])->where('e.entity_id > :entity_id')->order('e.entity_id')->limit($this->_productLimit); if ($productIds !== null) { $select->where('e.entity_id IN(?)', $productIds); } $rowSet = $connection->fetchAll($select, $bind); foreach ($rowSet as $row) { $product = new \Magento\Framework\DataObject($row); $product->setId($row['entity_id']); $product->setEntityId($row['entity_id']); $product->setCategoryIds([]); $product->setStoreId($storeId); $products[$product->getId()] = $product; $lastEntityId = $product->getId(); } unset($rowSet); if ($products) { $select = $connection->select()->from($this->getTable('catalog_category_product'), ['product_id', 'category_id'])->where('product_id IN(?)', array_keys($products)); $categories = $connection->fetchAll($select); foreach ($categories as $category) { $productId = $category['product_id']; $categoryIds = $products[$productId]->getCategoryIds(); $categoryIds[] = $category['category_id']; $products[$productId]->setCategoryIds($categoryIds); } foreach (['name', 'url_key', 'url_path'] as $attributeCode) { $attributes = $this->_getProductAttribute($attributeCode, array_keys($products), $storeId); foreach ($attributes as $productId => $attributeValue) { $products[$productId]->setData($attributeCode, $attributeValue); } } } return $products; }