/** * Prepare product and its configuration to be added to some products list. * Perform standard preparation process and then prepare of bundle selections options. * * @param \Magento\Framework\DataObject $buyRequest * @param \Magento\Catalog\Model\Product $product * @param string $processMode * @return \Magento\Framework\Phrase|array|string * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ protected function _prepareProduct(\Magento\Framework\DataObject $buyRequest, $product, $processMode) { $result = parent::_prepareProduct($buyRequest, $product, $processMode); try { if (is_string($result)) { throw new \Magento\Framework\Exception\LocalizedException(__($result)); } $selections = []; $isStrictProcessMode = $this->_isStrictProcessMode($processMode); $skipSaleableCheck = $this->_catalogProduct->getSkipSaleableCheck(); $_appendAllSelections = (bool) $product->getSkipCheckRequiredOption() || $skipSaleableCheck; $options = $buyRequest->getBundleOption(); if (is_array($options)) { $options = $this->recursiveIntval($options); $optionIds = array_keys($options); if (empty($optionIds) && $isStrictProcessMode) { throw new \Magento\Framework\Exception\LocalizedException(__('Please specify product option(s).')); } $product->getTypeInstance()->setStoreFilter($product->getStoreId(), $product); $optionsCollection = $this->getOptionsCollection($product); $this->checkIsAllRequiredOptions($product, $isStrictProcessMode, $optionsCollection, $options); $selectionIds = $this->multiToFlatArray($options); // If product has not been configured yet then $selections array should be empty if (!empty($selectionIds)) { $selections = $this->getSelectionsByIds($selectionIds, $product); if (count($selections->getItems()) !== count($selectionIds)) { throw new \Magento\Framework\Exception\LocalizedException(__('The options you selected are not available.')); } // Check if added selections are still on sale $this->checkSelectionsIsSale($selections, $skipSaleableCheck, $optionsCollection, $options); $optionsCollection->appendSelections($selections, false, $_appendAllSelections); $selections = $selections->getItems(); } else { $selections = []; } } else { $product->setOptionsValidationFail(true); $product->getTypeInstance()->setStoreFilter($product->getStoreId(), $product); $optionCollection = $product->getTypeInstance()->getOptionsCollection($product); $optionIds = $product->getTypeInstance()->getOptionsIds($product); $selectionCollection = $product->getTypeInstance()->getSelectionsCollection($optionIds, $product); $options = $optionCollection->appendSelections($selectionCollection, false, $_appendAllSelections); $selections = $this->mergeSelectionsWithOptions($options, $selections); } if (count($selections) > 0 || !$isStrictProcessMode) { $uniqueKey = [$product->getId()]; $selectionIds = []; $qtys = $buyRequest->getBundleOptionQty(); // Shuffle selection array by option position usort($selections, [$this, 'shakeSelections']); foreach ($selections as $selection) { $selectionOptionId = $selection->getOptionId(); $qty = $this->getQty($selection, $qtys, $selectionOptionId); $selectionId = $selection->getSelectionId(); $product->addCustomOption('selection_qty_' . $selectionId, $qty, $selection); $selection->addCustomOption('selection_id', $selectionId); $beforeQty = $this->getBeforeQty($product, $selection); $product->addCustomOption('product_qty_' . $selection->getId(), $qty + $beforeQty, $selection); /* * Create extra attributes that will be converted to product options in order item * for selection (not for all bundle) */ $price = $product->getPriceModel()->getSelectionFinalTotalPrice($product, $selection, 0, $qty); $attributes = ['price' => $this->priceCurrency->convert($price), 'qty' => $qty, 'option_label' => $selection->getOption()->getTitle(), 'option_id' => $selection->getOption()->getId()]; $_result = $selection->getTypeInstance()->prepareForCart($buyRequest, $selection); $this->checkIsResult($_result); $result[] = $_result[0]->setParentProductId($product->getId())->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds)))->addCustomOption('bundle_selection_attributes', serialize($attributes)); if ($isStrictProcessMode) { $_result[0]->setCartQty($qty); } $resultSelectionId = $_result[0]->getSelectionId(); $selectionIds[] = $resultSelectionId; $uniqueKey[] = $resultSelectionId; $uniqueKey[] = $qty; } // "unique" key for bundle selection and add it to selections and bundle for selections $uniqueKey = implode('_', $uniqueKey); foreach ($result as $item) { $item->addCustomOption('bundle_identity', $uniqueKey); } $product->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds))); $product->addCustomOption('bundle_selection_ids', serialize($selectionIds)); return $result; } } catch (\Magento\Framework\Exception\LocalizedException $e) { return $e->getMessage(); } return $this->getSpecifyOptionMessage(); }
/** * Prepare product and its configuration to be added to some products list. * Perform standard preparation process and then add Configurable specific options. * * @param \Magento\Framework\Object $buyRequest * @param \Magento\Catalog\Model\Product $product * @param string $processMode * @return \Magento\Framework\Phrase|array|string * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _prepareProduct(\Magento\Framework\Object $buyRequest, $product, $processMode) { $attributes = $buyRequest->getSuperAttribute(); if ($attributes || !$this->_isStrictProcessMode($processMode)) { if (!$this->_isStrictProcessMode($processMode)) { if (is_array($attributes)) { foreach ($attributes as $key => $val) { if (empty($val)) { unset($attributes[$key]); } } } else { $attributes = []; } } $result = parent::_prepareProduct($buyRequest, $product, $processMode); if (is_array($result)) { /** * $attributes = array($attributeId=>$attributeValue) */ $subProduct = true; if ($this->_isStrictProcessMode($processMode)) { foreach ($this->getConfigurableAttributes($product) as $attributeItem) { /* @var $attributeItem \Magento\Framework\Object */ $attrId = $attributeItem->getData('attribute_id'); if (!isset($attributes[$attrId]) || empty($attributes[$attrId])) { $subProduct = null; break; } } } if ($subProduct) { $subProduct = $this->getProductByAttributes($attributes, $product); } if ($subProduct) { $product->addCustomOption('attributes', serialize($attributes)); $product->addCustomOption('product_qty_' . $subProduct->getId(), 1, $subProduct); $product->addCustomOption('simple_product', $subProduct->getId(), $subProduct); $_result = $subProduct->getTypeInstance()->processConfiguration($buyRequest, $subProduct, $processMode); if (is_string($_result) && !is_array($_result)) { return $_result; } if (!isset($_result[0])) { return __('You can\'t add the item to shopping cart.')->render(); } /** * Adding parent product custom options to child product * to be sure that it will be unique as its parent */ if ($optionIds = $product->getCustomOption('option_ids')) { $optionIds = explode(',', $optionIds->getValue()); foreach ($optionIds as $optionId) { if ($option = $product->getCustomOption('option_' . $optionId)) { $_result[0]->addCustomOption('option_' . $optionId, $option->getValue()); } } } $_result[0]->setParentProductId($product->getId())->addCustomOption('parent_product_id', $product->getId()); if ($this->_isStrictProcessMode($processMode)) { $_result[0]->setCartQty(1); } $result[] = $_result[0]; return $result; } else { if (!$this->_isStrictProcessMode($processMode)) { return $result; } } } } return $this->getSpecifyOptionMessage()->render(); }
/** * Prepare product and its configuration to be added to some products list. * Perform standard preparation process and then prepare of bundle selections options. * * @param \Magento\Framework\Object $buyRequest * @param \Magento\Catalog\Model\Product $product * @param string $processMode * @return array|string */ protected function _prepareProduct(\Magento\Framework\Object $buyRequest, $product, $processMode) { $result = parent::_prepareProduct($buyRequest, $product, $processMode); if (is_string($result)) { return $result; } $selections = array(); $isStrictProcessMode = $this->_isStrictProcessMode($processMode); $skipSaleableCheck = $this->_catalogProduct->getSkipSaleableCheck(); $_appendAllSelections = (bool) $product->getSkipCheckRequiredOption() || $skipSaleableCheck; $options = $buyRequest->getBundleOption(); if (is_array($options)) { $options = array_filter($options, 'intval'); $qtys = $buyRequest->getBundleOptionQty(); foreach ($options as $_optionId => $_selections) { if (empty($_selections)) { unset($options[$_optionId]); } } $optionIds = array_keys($options); if (empty($optionIds) && $isStrictProcessMode) { return __('Please specify product option(s).'); } $product->getTypeInstance()->setStoreFilter($product->getStoreId(), $product); $optionsCollection = $this->getOptionsCollection($product); if (!$product->getSkipCheckRequiredOption() && $isStrictProcessMode) { foreach ($optionsCollection->getItems() as $option) { if ($option->getRequired() && !isset($options[$option->getId()])) { return __('Please select all required options.'); } } } $selectionIds = array(); foreach ($options as $selectionId) { if (!is_array($selectionId)) { if ($selectionId != '') { $selectionIds[] = (int) $selectionId; } } else { foreach ($selectionId as $id) { if ($id != '') { $selectionIds[] = (int) $id; } } } } // If product has not been configured yet then $selections array should be empty if (!empty($selectionIds)) { $selections = $this->getSelectionsByIds($selectionIds, $product); // Check if added selections are still on sale foreach ($selections->getItems() as $selection) { if (!$selection->isSalable() && !$skipSaleableCheck) { $_option = $optionsCollection->getItemById($selection->getOptionId()); if (is_array($options[$_option->getId()]) && count($options[$_option->getId()]) > 1) { $moreSelections = true; } else { $moreSelections = false; } if ($_option->getRequired() && (!$_option->isMultiSelection() || $_option->isMultiSelection() && !$moreSelections)) { return __('The required options you selected are not available.'); } } } $optionsCollection->appendSelections($selections, false, $_appendAllSelections); $selections = $selections->getItems(); } else { $selections = array(); } } else { $product->setOptionsValidationFail(true); $product->getTypeInstance()->setStoreFilter($product->getStoreId(), $product); $optionCollection = $product->getTypeInstance()->getOptionsCollection($product); $optionIds = $product->getTypeInstance()->getOptionsIds($product); $selectionCollection = $product->getTypeInstance()->getSelectionsCollection($optionIds, $product); $options = $optionCollection->appendSelections($selectionCollection, false, $_appendAllSelections); foreach ($options as $option) { if ($option->getRequired() && count($option->getSelections()) == 1) { $selections = array_merge($selections, $option->getSelections()); } else { $selections = array(); break; } } } if (count($selections) > 0 || !$isStrictProcessMode) { $uniqueKey = array($product->getId()); $selectionIds = array(); // Shuffle selection array by option position usort($selections, array($this, 'shakeSelections')); foreach ($selections as $selection) { if ($selection->getSelectionCanChangeQty() && isset($qtys[$selection->getOptionId()])) { $qty = (double) $qtys[$selection->getOptionId()] > 0 ? $qtys[$selection->getOptionId()] : 1; } else { $qty = (double) $selection->getSelectionQty() ? $selection->getSelectionQty() : 1; } $qty = (double) $qty; $product->addCustomOption('selection_qty_' . $selection->getSelectionId(), $qty, $selection); $selection->addCustomOption('selection_id', $selection->getSelectionId()); $beforeQty = 0; $customOption = $product->getCustomOption('product_qty_' . $selection->getId()); if ($customOption && $customOption->getProduct()->getId() == $selection->getId()) { $beforeQty = (double) $customOption->getValue(); } $product->addCustomOption('product_qty_' . $selection->getId(), $qty + $beforeQty, $selection); /* * Create extra attributes that will be converted to product options in order item * for selection (not for all bundle) */ $price = $product->getPriceModel()->getSelectionFinalTotalPrice($product, $selection, 0, $qty); $attributes = array('price' => $this->priceCurrency->convert($price), 'qty' => $qty, 'option_label' => $selection->getOption()->getTitle(), 'option_id' => $selection->getOption()->getId()); $_result = $selection->getTypeInstance()->prepareForCart($buyRequest, $selection); if (is_string($_result) && !is_array($_result)) { return $_result; } if (!isset($_result[0])) { return __('We cannot add this item to your shopping cart.'); } $result[] = $_result[0]->setParentProductId($product->getId())->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds)))->addCustomOption('bundle_selection_attributes', serialize($attributes)); if ($isStrictProcessMode) { $_result[0]->setCartQty($qty); } $selectionIds[] = $_result[0]->getSelectionId(); $uniqueKey[] = $_result[0]->getSelectionId(); $uniqueKey[] = $qty; } // "unique" key for bundle selection and add it to selections and bundle for selections $uniqueKey = implode('_', $uniqueKey); foreach ($result as $item) { $item->addCustomOption('bundle_identity', $uniqueKey); } $product->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds))); $product->addCustomOption('bundle_selection_ids', serialize($selectionIds)); return $result; } return $this->getSpecifyOptionMessage(); }