/** * Get configurations from product * * @param \Magento\Catalog\Model\Product $configurableProduct * @return array */ private function getConfigurationsFromProduct(\Magento\Catalog\Model\Product $configurableProduct) { $result = []; $configurableMatrix = $configurableProduct->hasData('configurable-matrix') ? $configurableProduct->getData('configurable-matrix') : []; foreach ($configurableMatrix as $item) { if (!$item['newProduct']) { $result[$item['id']] = $this->mapData($item); if (isset($item['qty'])) { $result[$item['id']]['quantity_and_stock_status']['qty'] = $item['qty']; } } } return $result; }
/** * Retrieve Product Attribute Value * * @param Product $product * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute * @return \Magento\Framework\Phrase|string */ public function getProductAttributeValue($product, $attribute) { if (!$product->hasData($attribute->getAttributeCode())) { return __('N/A'); } if ($attribute->getSourceModel() || in_array($attribute->getFrontendInput(), ['select', 'boolean', 'multiselect'])) { //$value = $attribute->getSource()->getOptionText($product->getData($attribute->getAttributeCode())); $value = $attribute->getFrontend()->getValue($product); } else { $value = $product->getData($attribute->getAttributeCode()); } return (string) $value == '' ? __('No') : $value; }
/** * Retrieve array of "subproducts" * * @param \Magento\Catalog\Model\Product $product * @param array $requiredAttributeIds * @return array */ public function getUsedProducts($product, $requiredAttributeIds = null) { \Magento\Framework\Profiler::start('CONFIGURABLE:' . __METHOD__, ['group' => 'CONFIGURABLE', 'method' => __METHOD__]); if (!$product->hasData($this->_usedProducts)) { if (is_null($requiredAttributeIds) && is_null($product->getData($this->_configurableAttributes))) { // If used products load before attributes, we will load attributes. $this->getConfigurableAttributes($product); // After attributes loading products loaded too. \Magento\Framework\Profiler::stop('CONFIGURABLE:' . __METHOD__); return $product->getData($this->_usedProducts); } $usedProducts = []; $collection = $this->getUsedProductCollection($product)->addAttributeToSelect('*')->addFilterByRequiredOptions()->setStoreId($product->getStoreId()); if (is_array($requiredAttributeIds)) { foreach ($requiredAttributeIds as $attributeId) { $attribute = $this->getAttributeById($attributeId, $product); if (!is_null($attribute)) { $collection->addAttributeToFilter($attribute->getAttributeCode(), ['notnull' => 1]); } } } foreach ($collection as $item) { $usedProducts[] = $item; } $product->setData($this->_usedProducts, $usedProducts); } \Magento\Framework\Profiler::stop('CONFIGURABLE:' . __METHOD__); return $product->getData($this->_usedProducts); }
/** * Get weee tax amount for product based on website * * @param \Magento\Catalog\Model\Product $product * @param mixed $website * @return float */ public function getAmount($product, $website = null) { if (!$product->hasData($this->cacheProductWeeeAmount)) { /** @var \Magento\Store\Model\Store $store */ if ($website) { $store = $this->_storeManager->getWebsite($website)->getDefaultGroup()->getDefaultStore(); } else { $store = $product->getStore(); } $amount = 0; if ($this->isEnabled($store)) { $amount = $this->_weeeTax->getWeeeAmount($product, null, null, $website); } $product->setData($this->cacheProductWeeeAmount, $amount); } return $product->getData($this->cacheProductWeeeAmount); }
/** * Retrieve bundle selections collection based on used options * * @param array $optionIds * @param \Magento\Catalog\Model\Product $product * @return \Magento\Bundle\Model\ResourceModel\Selection\Collection */ public function getSelectionsCollection($optionIds, $product) { $keyOptionIds = is_array($optionIds) ? implode('_', $optionIds) : ''; $key = $this->_keySelectionsCollection . $keyOptionIds; if (!$product->hasData($key)) { $storeId = $product->getStoreId(); $selectionsCollection = $this->_bundleCollection->create()->addAttributeToSelect($this->_config->getProductAttributes())->addAttributeToSelect('tax_class_id')->setFlag('require_stock_items', true)->setFlag('product_children', true)->setPositionOrder()->addStoreFilter($this->getStoreFilter($product))->setStoreId($storeId)->addFilterByRequiredOptions()->setOptionIdsFilter($optionIds); if (!$this->_catalogData->isPriceGlobal() && $storeId) { $websiteId = $this->_storeManager->getStore($storeId)->getWebsiteId(); $selectionsCollection->joinPrices($websiteId); } $product->setData($key, $selectionsCollection); } return $product->getData($key); }
/** * Check if product has links * * @param \Magento\Catalog\Model\Product $product * @return boolean */ public function hasLinks($product) { if ($product->hasData('links_exist')) { return $product->getData('links_exist'); } return count($this->getLinks($product)) > 0; }
/** * Retrieve array of "subproducts" * * @param \Magento\Catalog\Model\Product $product * @param array $requiredAttributeIds * @return array */ public function getUsedProducts($product, $requiredAttributeIds = null) { \Magento\Framework\Profiler::start('CONFIGURABLE:' . __METHOD__, ['group' => 'CONFIGURABLE', 'method' => __METHOD__]); if (!$product->hasData($this->_usedProducts)) { $usedProducts = []; $collection = $this->getUsedProductCollection($product)->addAttributeToSelect('*')->addAttributeToSelect('media_gallery')->addFilterByRequiredOptions()->setStoreId($product->getStoreId()); if (is_array($requiredAttributeIds)) { foreach ($requiredAttributeIds as $attributeId) { $attribute = $this->getAttributeById($attributeId, $product); if (!is_null($attribute)) { $collection->addAttributeToFilter($attribute->getAttributeCode(), ['notnull' => 1]); } } } foreach ($collection as $item) { /** @var \Magento\Catalog\Model\Product $item */ $item->getResource()->getAttribute('media_gallery')->getBackend()->afterLoad($item); $usedProducts[] = $item; } $product->setData($this->_usedProducts, $usedProducts); } \Magento\Framework\Profiler::stop('CONFIGURABLE:' . __METHOD__); return $product->getData($this->_usedProducts); }
/** * Retrieve related products identifiers * * @param \Magento\Catalog\Model\Product $product * @return array */ public function getAssociatedProductIds($product) { if (!$product->hasData($this->_keyAssociatedProductIds)) { $associatedProductIds = []; /** @var $item \Magento\Catalog\Model\Product */ foreach ($this->getAssociatedProducts($product) as $item) { $associatedProductIds[] = $item->getId(); } $product->setData($this->_keyAssociatedProductIds, $associatedProductIds); } return $product->getData($this->_keyAssociatedProductIds); }
/** * {@inheritdoc} */ public function hasData($key = '') { $pluginInfo = $this->pluginList->getNext($this->subjectType, 'hasData'); if (!$pluginInfo) { return parent::hasData($key); } else { return $this->___callPlugins('hasData', func_get_args(), $pluginInfo); } }
/** * Check is product available for sale * * @param \Magento\Catalog\Model\Product $product * @return bool */ public function isSalable($product) { $salable = $product->getStatus() == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED; if ($salable && $product->hasData('is_salable')) { $salable = $product->getData('is_salable'); } return (bool) (int) $salable; }
/** * @param \Magento\Catalog\Model\Product $product * @param array $rowData * @return void */ protected function setStoreToProduct(\Magento\Catalog\Model\Product $product, array $rowData) { if (!empty($rowData[ImportProduct::COL_STORE]) && ($storeId = $this->import->getStoreIdByCode($rowData[ImportProduct::COL_STORE]))) { $product->setStoreId($storeId); } elseif (!$product->hasData(\Magento\Catalog\Model\Product::STORE_ID)) { $product->setStoreId(Store::DEFAULT_STORE_ID); } }
/** * Retrieve array of "subproducts" * * @param \Magento\Catalog\Model\Product $product * @param array $requiredAttributeIds * @return array */ public function getUsedProducts($product, $requiredAttributeIds = null) { \Magento\Framework\Profiler::start('CONFIGURABLE:' . __METHOD__, ['group' => 'CONFIGURABLE', 'method' => __METHOD__]); if (!$product->hasData($this->_usedProducts)) { $metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class); $productId = $product->getData($metadata->getLinkField()); $key = md5(implode('_', [__METHOD__, $productId, $product->getStoreId(), $this->getCustomerSession()->getCustomerGroupId(), json_encode($requiredAttributeIds)])); $collection = $this->getUsedProductCollection($product); $data = unserialize($this->getCache()->load($key)); if (!empty($data)) { $usedProducts = []; foreach ($data as $item) { $productItem = $collection->getNewEmptyItem()->setData($item); $usedProducts[] = $productItem; } } else { $collection->setFlag('has_stock_status_filter', true)->addAttributeToSelect($this->getCatalogConfig()->getProductAttributes())->addFilterByRequiredOptions()->setStoreId($product->getStoreId()); $requiredAttributes = ['name', 'price', 'weight', 'image', 'thumbnail', 'status', 'media_gallery']; foreach ($requiredAttributes as $attributeCode) { $collection->addAttributeToSelect($attributeCode); } foreach ($this->getUsedProductAttributes($product) as $usedProductAttribute) { $collection->addAttributeToSelect($usedProductAttribute->getAttributeCode()); } $collection->addMediaGalleryData(); $collection->addTierPriceData(); $usedProducts = $collection->getItems(); $this->getCache()->save(serialize(array_map(function ($item) { return $item->getData(); }, $usedProducts)), $key, array_merge($product->getIdentities(), [\Magento\Catalog\Model\Category::CACHE_TAG, \Magento\Catalog\Model\Product::CACHE_TAG, 'price', self::TYPE_CODE . '_' . $productId])); } $product->setData($this->_usedProducts, $usedProducts); } \Magento\Framework\Profiler::stop('CONFIGURABLE:' . __METHOD__); $usedProducts = $product->getData($this->_usedProducts); return $usedProducts; }
/** * Retrieve array of "subproducts" * * @param \Magento\Catalog\Model\Product $product * @param array $requiredAttributeIds * @return array */ public function getUsedProducts($product, $requiredAttributeIds = null) { \Magento\Framework\Profiler::start('CONFIGURABLE:' . __METHOD__, ['group' => 'CONFIGURABLE', 'method' => __METHOD__]); if (!$product->hasData($this->_usedProducts)) { $usedProducts = []; $collection = $this->getUsedProductCollection($product)->addAttributeToSelect('name')->addAttributeToSelect('price')->addAttributeToSelect('weight')->addAttributeToSelect('image')->addAttributeToSelect('thumbnail')->addAttributeToSelect('status')->addAttributeToSelect($this->getCatalogConfig()->getProductAttributes())->addFilterByRequiredOptions()->setStoreId($product->getStoreId()); if (is_array($requiredAttributeIds)) { foreach ($requiredAttributeIds as $attributeId) { $attribute = $this->getAttributeById($attributeId, $product); if (!is_null($attribute)) { $collection->addAttributeToFilter($attribute->getAttributeCode(), ['notnull' => 1]); } } } foreach ($collection as $item) { /** @var \Magento\Catalog\Model\Product $item */ $this->getGalleryReadHandler()->execute('', $item); $usedProducts[] = $item; } $product->setData($this->_usedProducts, $usedProducts); } \Magento\Framework\Profiler::stop('CONFIGURABLE:' . __METHOD__); return $product->getData($this->_usedProducts); }
/** * @param Product $product * @return array */ protected function buildTags(Product $product) { $tags = []; foreach ($product->getAttributes() as $attr) { if ($attr->getIsVisibleOnFront() && $product->hasData($attr->getAttributeCode())) { $label = $attr->getStoreLabel(); $value = $attr->getFrontend()->getValue($product); if (is_string($label) && strlen($label) && is_string($value) && strlen($value)) { $tags[] = "{$label}: {$value}"; } } } if (!$product->canConfigure()) { $tags[] = \NostoProduct::PRODUCT_ADD_TO_CART; } return $tags; }
/** * Initialize product from data * * @param \Magento\Catalog\Model\Product $product * @param array $productData * @return \Magento\Catalog\Model\Product * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function initializeFromData(\Magento\Catalog\Model\Product $product, array $productData) { unset($productData['custom_attributes']); unset($productData['extension_attributes']); if ($productData) { $stockData = isset($productData['stock_data']) ? $productData['stock_data'] : []; $productData['stock_data'] = $this->stockFilter->filter($stockData); } $productData = $this->normalize($productData); if (!empty($productData['is_downloadable'])) { $productData['product_has_weight'] = 0; } foreach (['category_ids', 'website_ids'] as $field) { if (!isset($productData[$field])) { $productData[$field] = []; } } foreach ($productData['website_ids'] as $websiteId => $checkboxValue) { if (!$checkboxValue) { unset($productData['website_ids'][$websiteId]); } } $wasLockedMedia = false; if ($product->isLockedAttribute('media')) { $product->unlockAttribute('media'); $wasLockedMedia = true; } $dateFieldFilters = []; $attributes = $product->getAttributes(); foreach ($attributes as $attrKey => $attribute) { if ($attribute->getBackend()->getType() == 'datetime') { if (array_key_exists($attrKey, $productData) && $productData[$attrKey] != '') { $dateFieldFilters[$attrKey] = $this->getDateTimeFilter(); } } } $inputFilter = new \Zend_Filter_Input($dateFieldFilters, [], $productData); $productData = $inputFilter->getUnescaped(); if (isset($productData['options'])) { $productOptions = $productData['options']; unset($productData['options']); } else { $productOptions = []; } $product->addData($productData); if ($wasLockedMedia) { $product->lockAttribute('media'); } /** * Check "Use Default Value" checkboxes values */ $useDefaults = (array) $this->request->getPost('use_default', []); foreach ($useDefaults as $attributeCode => $useDefaultState) { if ($useDefaultState) { $product->setData($attributeCode, null); // UI component sends value even if field is disabled, so 'Use Config Settings' must be reset to false if ($product->hasData('use_config_' . $attributeCode)) { $product->setData('use_config_' . $attributeCode, false); } } } $product = $this->setProductLinks($product); /** * Initialize product options */ if ($productOptions && !$product->getOptionsReadonly()) { // mark custom options that should to fall back to default value $options = $this->mergeProductOptions($productOptions, $this->request->getPost('options_use_default')); $customOptions = []; foreach ($options as $customOptionData) { if (empty($customOptionData['is_delete'])) { if (isset($customOptionData['values'])) { $customOptionData['values'] = array_filter($customOptionData['values'], function ($valueData) { return empty($valueData['is_delete']); }); } $customOption = $this->getCustomOptionFactory()->create(['data' => $customOptionData]); $customOption->setProductSku($product->getSku()); $customOption->setOptionId(null); $customOptions[] = $customOption; } } $product->setOptions($customOptions); } $product->setCanSaveCustomOptions(!empty($productData['affect_product_custom_options']) && !$product->getOptionsReadonly()); return $product; }