/** * @param Action\Context $context * @param \Magento\Catalog\Helper\Product $productHelper * @param \Magento\Framework\Escaper $escaper * @param PageFactory $resultPageFactory * @param ForwardFactory $resultForwardFactory */ public function __construct(Action\Context $context, \Magento\Catalog\Helper\Product $productHelper, \Magento\Framework\Escaper $escaper, PageFactory $resultPageFactory, ForwardFactory $resultForwardFactory) { parent::__construct($context); $productHelper->setSkipSaleableCheck(true); $this->escaper = $escaper; $this->resultPageFactory = $resultPageFactory; $this->resultForwardFactory = $resultForwardFactory; }
/** * Set current attribute to entry (for specified product) * * @param \Magento\Catalog\Model\Product $product * @param \Magento\Framework\Gdata\Gshopping\Entry $entry * @return \Magento\Framework\Gdata\Gshopping\Entry */ public function convertAttribute($product, $entry) { $url = $this->_catalogProduct->getImageUrl($product); if ($product->getImage() && $product->getImage() != 'no_selection' && $url) { $this->_setAttribute($entry, 'image_link', self::ATTRIBUTE_TYPE_URL, $url); } return $entry; }
/** * @param \Magento\Framework\Data\Form\Element\Factory $factoryElement * @param \Magento\Framework\Data\Form\Element\CollectionFactory $factoryCollection * @param \Magento\Framework\Escaper $escaper * @param \Magento\Catalog\Helper\Product $helper * @param array $data */ public function __construct(\Magento\Framework\Data\Form\Element\Factory $factoryElement, \Magento\Framework\Data\Form\Element\CollectionFactory $factoryCollection, \Magento\Framework\Escaper $escaper, \Magento\Catalog\Helper\Product $helper, array $data = []) { $this->_helper = $helper; $this->_virtual = $factoryElement->create('checkbox'); $this->_virtual->setId(self::VIRTUAL_FIELD_HTML_ID)->setName('is_virtual')->setLabel($this->_helper->getTypeSwitcherControlLabel()); $data['class'] = 'validate-number validate-zero-or-greater validate-number-range number-range-0-99999999.9999'; parent::__construct($factoryElement, $factoryCollection, $escaper, $data); }
/** * @return array */ public function getOptions() { if (!$this->options) { $product = $this->getProduct(); $typeInstance = $product->getTypeInstance(); $typeInstance->setStoreFilter($product->getStoreId(), $product); $optionCollection = $typeInstance->getOptionsCollection($product); $selectionCollection = $typeInstance->getSelectionsCollection($typeInstance->getOptionsIds($product), $product); $this->options = $optionCollection->appendSelections($selectionCollection, false, $this->catalogProduct->getSkipSaleableCheck()); } return $this->options; }
/** * Retrieve Visitor/Customer Last Viewed URL * * @return string */ public function getLastViewedUrl() { $productId = $this->_catalogSession->getLastViewedProductId(); if ($productId) { try { $product = $this->productRepository->getById($productId); } catch (NoSuchEntityException $e) { return ''; } /* @var $product \Magento\Catalog\Model\Product */ if ($this->_catalogProduct->canShow($product, 'catalog')) { return $product->getProductUrl(); } } $categoryId = $this->_catalogSession->getLastViewedCategoryId(); if ($categoryId) { try { $category = $this->categoryRepository->get($categoryId); } catch (NoSuchEntityException $e) { return ''; } /* @var $category \Magento\Catalog\Model\Category */ if (!$this->_catalogCategory->canShow($category)) { return ''; } return $category->getCategoryUrl(); } return ''; }
/** * Prepares and render result of composite product configuration request * * The $configureResult variable holds either: * - 'ok' = true, and 'product_id', 'buy_request', 'current_store_id', 'current_customer_id' * - 'error' = true, and 'message' to show * * @param \Magento\Framework\DataObject $configureResult * @return \Magento\Framework\View\Result\Layout */ public function renderConfigureResult(\Magento\Framework\DataObject $configureResult) { try { if (!$configureResult->getOk()) { throw new \Magento\Framework\Exception\LocalizedException(__($configureResult->getMessage())); } $currentStoreId = (int) $configureResult->getCurrentStoreId(); if (!$currentStoreId) { $currentStoreId = $this->_storeManager->getStore()->getId(); } $product = $this->productRepository->getById($configureResult->getProductId(), false, $currentStoreId); $this->_coreRegistry->register('current_product', $product); $this->_coreRegistry->register('product', $product); // Register customer we're working with $customerId = (int) $configureResult->getCurrentCustomerId(); $this->_coreRegistry->register(RegistryConstants::CURRENT_CUSTOMER_ID, $customerId); // Prepare buy request values $buyRequest = $configureResult->getBuyRequest(); if ($buyRequest) { $this->_catalogProduct->prepareProductOptions($product, $buyRequest); } $isOk = true; $productType = $product->getTypeId(); } catch (\Exception $e) { $isOk = false; $productType = null; $this->_coreRegistry->register('composite_configure_result_error_message', $e->getMessage()); } return $this->_initConfigureResultLayout($isOk, $productType); }
/** * Add meta information from product to head block * * @return \Magento\Catalog\Block\Product\View */ protected function _prepareLayout() { $this->getLayout()->createBlock('Magento\\Catalog\\Block\\Breadcrumbs'); $product = $this->getProduct(); if (!$product) { return parent::_prepareLayout(); } $title = $product->getMetaTitle(); if ($title) { $this->pageConfig->getTitle()->set($title); } $keyword = $product->getMetaKeyword(); $currentCategory = $this->_coreRegistry->registry('current_category'); if ($keyword) { $this->pageConfig->setKeywords($keyword); } elseif ($currentCategory) { $this->pageConfig->setKeywords($product->getName()); } $description = $product->getMetaDescription(); if ($description) { $this->pageConfig->setDescription($description); } else { $this->pageConfig->setDescription($this->string->substr($product->getDescription(), 0, 255)); } if ($this->_productHelper->canUseCanonicalTag()) { $this->pageConfig->addRemotePageAsset($product->getUrlModel()->getUrl($product, ['_ignore_category' => true]), 'canonical', ['attributes' => ['rel' => 'canonical']]); } $pageMainTitle = $this->getLayout()->getBlock('page.main.title'); if ($pageMainTitle) { $pageMainTitle->setPageTitle($product->getName()); } return parent::_prepareLayout(); }
/** * {@inheritdoc} */ public function create(\Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata $attributeMetadata) { /** * @var $model \Magento\Catalog\Model\Resource\Eav\Attribute */ $model = $this->attributeFactory->create(); $data = $attributeMetadata->__toArray(); // unset attribute id because we create new attribute (does not rewrite existing one) unset($data[AttributeMetadata::ATTRIBUTE_ID]); // define frontend label if (!$attributeMetadata->getFrontendLabel()) { throw InputException::requiredField(AttributeMetadata::FRONTEND_LABEL); } $data[AttributeMetadata::FRONTEND_LABEL] = []; foreach ($attributeMetadata->getFrontendLabel() as $label) { $data[AttributeMetadata::FRONTEND_LABEL][$label->getStoreId()] = $label->getLabel(); } if (!isset($data[AttributeMetadata::FRONTEND_LABEL][0]) || !$data[AttributeMetadata::FRONTEND_LABEL][0]) { throw InputException::invalidFieldValue(AttributeMetadata::FRONTEND_LABEL, null); } $data[AttributeMetadata::ATTRIBUTE_CODE] = $attributeMetadata->getAttributeCode() ?: $this->generateCode($data[AttributeMetadata::FRONTEND_LABEL][0]); $this->validateCode($data[AttributeMetadata::ATTRIBUTE_CODE]); $this->validateFrontendInput($attributeMetadata->getFrontendInput()); $data[AttributeMetadata::BACKEND_TYPE] = $model->getBackendTypeByInput($attributeMetadata->getFrontendInput()); $data[AttributeMetadata::SOURCE_MODEL] = $this->helper->getAttributeSourceModelByInputType($attributeMetadata->getFrontendInput()); $data[AttributeMetadata::BACKEND_MODEL] = $this->helper->getAttributeBackendModelByInputType($attributeMetadata->getFrontendInput()); $model->addData($data); $model->setEntityTypeId($this->eavConfig->getEntityType(\Magento\Catalog\Model\Product::ENTITY)->getId())->setIsUserDefined(1); return $model->save()->getAttributeCode(); }
/** * Check if product can be bought * * @param \Magento\Catalog\Model\Product $product * @return $this * @throws \Magento\Framework\Exception\LocalizedException */ public function checkProductBuyState($product) { parent::checkProductBuyState($product); $productOptionIds = $this->getOptionsIds($product); $productSelections = $this->getSelectionsCollection($productOptionIds, $product); $selectionIds = $product->getCustomOption('bundle_selection_ids'); $selectionIds = unserialize($selectionIds->getValue()); $buyRequest = $product->getCustomOption('info_buyRequest'); $buyRequest = new \Magento\Framework\DataObject(unserialize($buyRequest->getValue())); $bundleOption = $buyRequest->getBundleOption(); if (empty($bundleOption)) { throw new \Magento\Framework\Exception\LocalizedException($this->getSpecifyOptionMessage()); } $skipSaleableCheck = $this->_catalogProduct->getSkipSaleableCheck(); foreach ($selectionIds as $selectionId) { /* @var $selection \Magento\Bundle\Model\Selection */ $selection = $productSelections->getItemById($selectionId); if (!$selection || !$selection->isSalable() && !$skipSaleableCheck) { throw new \Magento\Framework\Exception\LocalizedException(__('The required options you selected are not available.')); } } $product->getTypeInstance()->setStoreFilter($product->getStoreId(), $product); $optionsCollection = $this->getOptionsCollection($product); foreach ($optionsCollection->getItems() as $option) { if ($option->getRequired() && empty($bundleOption[$option->getId()])) { throw new \Magento\Framework\Exception\LocalizedException(__('Please select all required options.')); } } return $this; }
/** * Add wishlist item to shopping cart and remove from wishlist * * If Product has required options - item removed from wishlist and redirect * to product view page with message about needed defined required options * * @return ResponseInterface * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function execute() { $itemId = (int) $this->getRequest()->getParam('item'); /* @var $item \Magento\Wishlist\Model\Item */ $item = $this->itemFactory->create()->load($itemId); if (!$item->getId()) { return $this->_redirect('*/*'); } $wishlist = $this->wishlistProvider->getWishlist($item->getWishlistId()); if (!$wishlist) { return $this->_redirect('*/*'); } // Set qty $qty = $this->getRequest()->getParam('qty'); if (is_array($qty)) { if (isset($qty[$itemId])) { $qty = $qty[$itemId]; } else { $qty = 1; } } $qty = $this->quantityProcessor->process($qty); if ($qty) { $item->setQty($qty); } $redirectUrl = $this->_url->getUrl('*/*'); $configureUrl = $this->_url->getUrl('*/*/configure/', ['id' => $item->getId(), 'product_id' => $item->getProductId()]); try { /** @var \Magento\Wishlist\Model\Resource\Item\Option\Collection $options */ $options = $this->optionFactory->create()->getCollection()->addItemFilter([$itemId]); $item->setOptions($options->getOptionsByItem($itemId)); $buyRequest = $this->productHelper->addParamsToBuyRequest($this->getRequest()->getParams(), ['current_config' => $item->getBuyRequest()]); $item->mergeBuyRequest($buyRequest); $item->addToCart($this->cart, true); $this->cart->save()->getQuote()->collectTotals(); $wishlist->save(); if (!$this->cart->getQuote()->getHasError()) { $message = __('You added %1 to your shopping cart.', $this->escaper->escapeHtml($item->getProduct()->getName())); $this->messageManager->addSuccess($message); } if ($this->cart->getShouldRedirectToCart()) { $redirectUrl = $this->cart->getCartUrl(); } else { $refererUrl = $this->_redirect->getRefererUrl(); if ($refererUrl && $refererUrl != $configureUrl) { $redirectUrl = $refererUrl; } } } catch (ProductException $e) { $this->messageManager->addError(__('This product(s) is out of stock.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addNotice($e->getMessage()); $redirectUrl = $configureUrl; } catch (\Exception $e) { $this->messageManager->addException($e, __('Cannot add item to shopping cart')); } $this->helper->calculate(); return $this->getResponse()->setRedirect($redirectUrl); }
/** * Update wishlist Item and set data from request * * The $params sets how current item configuration must be taken into account and additional options. * It's passed to \Magento\Catalog\Helper\Product->addParamsToBuyRequest() to compose resulting buyRequest. * * Basically it can hold * - 'current_config', \Magento\Framework\Object or array - current buyRequest that configures product in this item, * used to restore currently attached files * - 'files_prefix': string[a-z0-9_] - prefix that was added at frontend to names of file options (file inputs), * so they won't intersect with other submitted options * * For more options see \Magento\Catalog\Helper\Product->addParamsToBuyRequest() * * @param int|Item $itemId * @param \Magento\Framework\Object $buyRequest * @param null|array|\Magento\Framework\Object $params * @return $this * @throws Exception * * @see \Magento\Catalog\Helper\Product::addParamsToBuyRequest() */ public function updateItem($itemId, $buyRequest, $params = null) { $item = null; if ($itemId instanceof Item) { $item = $itemId; } else { $item = $this->getItem((int) $itemId); } if (!$item) { throw new Exception(__('We can\'t specify a wish list item.')); } $product = $item->getProduct(); $productId = $product->getId(); if ($productId) { if (!$params) { $params = new \Magento\Framework\Object(); } else { if (is_array($params)) { $params = new \Magento\Framework\Object($params); } } $params->setCurrentConfig($item->getBuyRequest()); $buyRequest = $this->_catalogProduct->addParamsToBuyRequest($buyRequest, $params); $product->setWishlistStoreId($item->getStoreId()); $items = $this->getItemCollection(); $isForceSetQuantity = true; foreach ($items as $_item) { /* @var $_item Item */ if ($_item->getProductId() == $product->getId() && $_item->representProduct($product) && $_item->getId() != $item->getId()) { // We do not add new wishlist item, but updating the existing one $isForceSetQuantity = false; } } $resultItem = $this->addNewItem($product, $buyRequest, $isForceSetQuantity); /** * Error message */ if (is_string($resultItem)) { throw new Exception(__($resultItem)); } if ($resultItem->getId() != $itemId) { if ($resultItem->getDescription() != $item->getDescription()) { $resultItem->setDescription($item->getDescription())->save(); } $item->isDeleted(true); $this->setDataChanges(true); } else { $resultItem->setQty($buyRequest->getQty() * 1); $resultItem->setOrigData('qty', 0); } } else { throw new Exception(__('The product does not exist.')); } return $this; }
/** * {@inheritdoc} * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function save(\Magento\Catalog\Api\Data\ProductAttributeInterface $attribute) { if ($attribute->getAttributeId()) { $existingModel = $this->get($attribute->getAttributeCode()); if (!$existingModel->getAttributeId()) { throw NoSuchEntityException::singleField('attribute_code', $existingModel->getAttributeCode()); } $attribute->setAttributeId($existingModel->getAttributeId()); $attribute->setIsUserDefined($existingModel->getIsUserDefined()); $attribute->setFrontendInput($existingModel->getFrontendInput()); if (is_array($attribute->getFrontendLabels())) { $frontendLabel[0] = $existingModel->getDefaultFrontendLabel(); foreach ($attribute->getFrontendLabels() as $item) { $frontendLabel[$item->getStoreId()] = $item->getLabel(); } $attribute->setDefaultFrontendLabel($frontendLabel); } if (!$attribute->getIsUserDefined()) { // Unset attribute field for system attributes $attribute->setApplyTo(null); } } else { $attribute->setAttributeId(null); if (!$attribute->getFrontendLabels() && !$attribute->getDefaultFrontendLabel()) { throw InputException::requiredField('frontend_label'); } $frontendLabels = []; if ($attribute->getDefaultFrontendLabel()) { $frontendLabels[0] = $attribute->getDefaultFrontendLabel(); } if ($attribute->getFrontendLabels() && is_array($attribute->getFrontendLabels())) { foreach ($attribute->getFrontendLabels() as $label) { $frontendLabels[$label->getStoreId()] = $label->getLabel(); } if (!isset($frontendLabels[0]) || !$frontendLabels[0]) { throw InputException::invalidFieldValue('frontend_label', null); } $attribute->setDefaultFrontendLabel($frontendLabels); } $attribute->setAttributeCode($attribute->getAttributeCode() ?: $this->generateCode($frontendLabels[0])); $this->validateCode($attribute->getAttributeCode()); $this->validateFrontendInput($attribute->getFrontendInput()); $attribute->setBackendType($attribute->getBackendTypeByInput($attribute->getFrontendInput())); $attribute->setSourceModel($this->productHelper->getAttributeSourceModelByInputType($attribute->getFrontendInput())); $attribute->setBackendModel($this->productHelper->getAttributeBackendModelByInputType($attribute->getFrontendInput())); $attribute->setEntityTypeId($this->eavConfig->getEntityType(\Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE)->getId()); $attribute->setIsUserDefined(1); } $this->attributeResource->save($attribute); foreach ($attribute->getOptions() as $option) { $this->optionManagement->add($attribute->getAttributeCode(), $option); } return $this->get($attribute->getAttributeCode()); }
public function testPrepareProductOptions() { /** @var $product \Magento\Catalog\Model\Product */ $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\\Catalog\\Model\\Product'); $buyRequest = new \Magento\Framework\DataObject(['qty' => 100, 'options' => ['option' => 'value']]); $this->_helper->prepareProductOptions($product, $buyRequest); $result = $product->getPreconfiguredValues(); $this->assertInstanceOf('Magento\\Framework\\DataObject', $result); $this->assertEquals(100, $result->getQty()); $this->assertEquals(['option' => 'value'], $result->getOptions()); }
/** * @param array $fixtures * @throws \Exception */ public function install(array $fixtures) { $attributeCount = 0; foreach ($fixtures as $fileName) { $fileName = $this->fixtureManager->getFixture($fileName); if (!file_exists($fileName)) { continue; } $rows = $this->csvReader->getData($fileName); $header = array_shift($rows); foreach ($rows as $row) { $data = []; foreach ($row as $key => $value) { $data[$header[$key]] = $value; } $data['attribute_set'] = explode("\n", $data['attribute_set']); /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */ $attribute = $this->eavConfig->getAttribute('catalog_product', $data['attribute_code']); if (!$attribute) { $attribute = $this->attributeFactory->create(); } $frontendLabel = explode("\n", $data['frontend_label']); if (count($frontendLabel) > 1) { $data['frontend_label'] = []; $data['frontend_label'][\Magento\Store\Model\Store::DEFAULT_STORE_ID] = $frontendLabel[0]; $data['frontend_label'][$this->storeManager->getDefaultStoreView()->getStoreId()] = $frontendLabel[1]; } $data['option'] = $this->getOption($attribute, $data); $data['source_model'] = $this->productHelper->getAttributeSourceModelByInputType($data['frontend_input']); $data['backend_model'] = $this->productHelper->getAttributeBackendModelByInputType($data['frontend_input']); $data += ['is_filterable' => 0, 'is_filterable_in_search' => 0, 'apply_to' => []]; $data['backend_type'] = $attribute->getBackendTypeByInput($data['frontend_input']); $attribute->addData($data); $attribute->setIsUserDefined(1); $attribute->setEntityTypeId($this->getEntityTypeId()); $attribute->save(); $attributeId = $attribute->getId(); if (is_array($data['attribute_set'])) { foreach ($data['attribute_set'] as $setName) { $setName = trim($setName); $attributeCount++; $attributeSet = $this->processAttributeSet($setName); $attributeGroupId = $attributeSet->getDefaultGroupId(); $attribute = $this->attributeFactory->create(); $attribute->setId($attributeId)->setAttributeGroupId($attributeGroupId)->setAttributeSetId($attributeSet->getId())->setEntityTypeId($this->getEntityTypeId())->setSortOrder($attributeCount + 999)->save(); } } } } $this->eavConfig->clear(); }
/** * {@inheritdoc} */ public function run() { $this->logger->log('Installing catalog attributes:'); $attributeCount = 0; foreach ($this->moduleList->getNames() as $moduleName) { $fileName = substr($moduleName, strpos($moduleName, "_") + 1) . '/attributes.csv'; $fileName = $this->fixtureHelper->getPath($fileName); if (!$fileName) { continue; } $csvReader = $this->csvReaderFactory->create(['fileName' => $fileName, 'mode' => 'r']); foreach ($csvReader as $data) { $data['attribute_set'] = explode("\n", $data['attribute_set']); /** @var \Magento\Catalog\Model\Resource\Eav\Attribute $attribute */ $attribute = $this->eavConfig->getAttribute('catalog_product', $data['attribute_code']); if (!$attribute) { $attribute = $this->attributeFactory->create(); } $frontendLabel = explode("\n", $data['frontend_label']); if (count($frontendLabel) > 1) { $data['frontend_label'] = []; $data['frontend_label'][\Magento\Store\Model\Store::DEFAULT_STORE_ID] = $frontendLabel[0]; $data['frontend_label'][$this->storeManager->getStoreId()] = $frontendLabel[1]; } $data['option'] = $this->getOption($attribute, $data); $data['source_model'] = $this->productHelper->getAttributeSourceModelByInputType($data['frontend_input']); $data['backend_model'] = $this->productHelper->getAttributeBackendModelByInputType($data['frontend_input']); $data += ['is_filterable' => 0, 'is_filterable_in_search' => 0, 'apply_to' => []]; $data['backend_type'] = $attribute->getBackendTypeByInput($data['frontend_input']); $attribute->addData($data); $attribute->setIsUserDefined(1); $attribute->setEntityTypeId($this->getEntityTypeId()); $attribute->save(); $attributeId = $attribute->getId(); if (is_array($data['attribute_set'])) { foreach ($data['attribute_set'] as $setName) { $setName = trim($setName); $attributeCount++; $attributeSet = $this->processAttributeSet($setName); $attributeGroupId = $attributeSet->getDefaultGroupId(); $attribute = $this->attributeFactory->create(); $attribute->setId($attributeId)->setAttributeGroupId($attributeGroupId)->setAttributeSetId($attributeSet->getId())->setEntityTypeId($this->getEntityTypeId())->setSortOrder($attributeCount + 999)->save(); } } $this->logger->logInline('.'); } } $this->eavConfig->clear(); }
/** * Get Allowed Products * * @return array */ public function getAllowProducts() { if (!$this->hasAllowProducts()) { $products = []; $skipSaleableCheck = $this->catalogProduct->getSkipSaleableCheck(); $allProducts = $this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct(), null); foreach ($allProducts as $product) { if ($product->isSaleable() || $skipSaleableCheck) { $products[] = $product; } } $this->setAllowProducts($products); } return $this->getData('allow_products'); }
/** * Add new product attrubute into all attribute sets. * If attribute is already exists - skip. * * @param array $data Array of slider data arrays * <pre> * [ * attribute_code * is_global * frontend_input [text|boolean|textarea|select|price|media_image|etc] * default_value_text * is_searchable * is_visible_in_advanced_search * is_comparable * frontend_label array * sort_order Set 0 to use MaxSortOrder * ] * </pre> * @return void */ public function execute($data) { $defaults = array('is_global' => 0, 'frontend_input' => 'boolean', 'is_configurable' => 0, 'is_filterable' => 0, 'is_filterable_in_search' => 0, 'sort_order' => 1); $entityTypeId = $this->objectManager->create('Magento\\Eav\\Model\\Entity')->setType(\Magento\Catalog\Model\Product::ENTITY)->getTypeId(); $attributeSets = $this->objectManager->create('Magento\\Eav\\Model\\ResourceModel\\Entity\\Attribute\\Set\\Collection')->setEntityTypeFilter($entityTypeId); foreach ($data as $itemData) { /* @var $model \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ $model = $this->attributeFactory->create()->load($itemData['attribute_code'], 'attribute_code'); if ($model->getId()) { continue; } $itemData = array_merge($itemData, $defaults); $itemData['source_model'] = $this->productHelper->getAttributeSourceModelByInputType($itemData['frontend_input']); $itemData['backend_model'] = $this->productHelper->getAttributeBackendModelByInputType($itemData['frontend_input']); $itemData['backend_type'] = $model->getBackendTypeByInput($itemData['frontend_input']); $model->addData($itemData); $model->setEntityTypeId($entityTypeId); $model->setIsUserDefined(1); foreach ($attributeSets as $set) { $model->setAttributeSetId($set->getId()); $model->setAttributeGroupId($set->getDefaultGroupId()); try { $model->save(); } catch (\Exception $e) { $this->fault('product_attribute_save', $e); } } if (!$attributeSets->count()) { try { $model->save(); } catch (\Exception $e) { $this->fault('product_attribute_save', $e); } } } }
/** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testExecuteWithoutQuantityArrayAndConfigurable() { $itemId = 2; $wishlistId = 1; $qty = []; $productId = 4; $indexUrl = 'index_url'; $configureUrl = 'configure_url'; $options = [5 => 'option']; $params = ['item' => $itemId, 'qty' => $qty]; $this->formKeyValidator->expects($this->once())->method('validate')->with($this->requestMock)->willReturn(true); $itemMock = $this->getMockBuilder('Magento\\Wishlist\\Model\\Item')->disableOriginalConstructor()->setMethods(['load', 'getId', 'getWishlistId', 'setQty', 'setOptions', 'getBuyRequest', 'mergeBuyRequest', 'addToCart', 'getProduct', 'getProductId'])->getMock(); $this->requestMock->expects($this->at(0))->method('getParam')->with('item', null)->willReturn($itemId); $this->itemFactoryMock->expects($this->once())->method('create')->willReturn($itemMock); $itemMock->expects($this->once())->method('load')->with($itemId, null)->willReturnSelf(); $itemMock->expects($this->exactly(2))->method('getId')->willReturn($itemId); $itemMock->expects($this->once())->method('getWishlistId')->willReturn($wishlistId); $wishlistMock = $this->getMockBuilder('Magento\\Wishlist\\Model\\Wishlist')->disableOriginalConstructor()->getMock(); $this->wishlistProviderMock->expects($this->once())->method('getWishlist')->with($wishlistId)->willReturn($wishlistMock); $this->requestMock->expects($this->at(1))->method('getParam')->with('qty', null)->willReturn($qty); $this->quantityProcessorMock->expects($this->once())->method('process')->with(1)->willReturnArgument(0); $itemMock->expects($this->once())->method('setQty')->with(1)->willReturnSelf(); $this->urlMock->expects($this->at(0))->method('getUrl')->with('*/*', null)->willReturn($indexUrl); $itemMock->expects($this->once())->method('getProductId')->willReturn($productId); $this->urlMock->expects($this->at(1))->method('getUrl')->with('*/*/configure/', ['id' => $itemId, 'product_id' => $productId])->willReturn($configureUrl); $optionMock = $this->getMockBuilder('Magento\\Wishlist\\Model\\Item\\Option')->disableOriginalConstructor()->getMock(); $this->optionFactoryMock->expects($this->once())->method('create')->willReturn($optionMock); $optionsMock = $this->getMockBuilder('Magento\\Wishlist\\Model\\ResourceModel\\Item\\Option\\Collection')->disableOriginalConstructor()->getMock(); $optionMock->expects($this->once())->method('getCollection')->willReturn($optionsMock); $optionsMock->expects($this->once())->method('addItemFilter')->with([$itemId])->willReturnSelf(); $optionsMock->expects($this->once())->method('getOptionsByItem')->with($itemId)->willReturn($options); $itemMock->expects($this->once())->method('setOptions')->with($options)->willReturnSelf(); $this->requestMock->expects($this->once())->method('getParams')->willReturn($params); $buyRequestMock = $this->getMockBuilder('Magento\\Framework\\DataObject')->disableOriginalConstructor()->getMock(); $itemMock->expects($this->once())->method('getBuyRequest')->willReturn($buyRequestMock); $this->productHelperMock->expects($this->once())->method('addParamsToBuyRequest')->with($params, ['current_config' => $buyRequestMock])->willReturn($buyRequestMock); $itemMock->expects($this->once())->method('mergeBuyRequest')->with($buyRequestMock)->willReturnSelf(); $itemMock->expects($this->once())->method('addToCart')->with($this->checkoutCartMock, true)->willThrowException(new \Magento\Framework\Exception\LocalizedException(__('message'))); $this->messageManagerMock->expects($this->once())->method('addNotice')->with('message', null)->willReturnSelf(); $this->helperMock->expects($this->once())->method('calculate')->willReturnSelf(); $this->resultRedirectMock->expects($this->once())->method('setUrl')->with($configureUrl)->willReturnSelf(); $this->assertSame($this->resultRedirectMock, $this->model->execute()); }
/** * Retrieve Visitor/Customer Last Viewed URL * * @return string */ public function getLastViewedUrl() { $productId = $this->_catalogSession->getLastViewedProductId(); if ($productId) { $product = $this->_productFactory->create()->load($productId); /* @var $product \Magento\Catalog\Model\Product */ if ($this->_catalogProduct->canShow($product, 'catalog')) { return $product->getProductUrl(); } } $categoryId = $this->_catalogSession->getLastViewedCategoryId(); if ($categoryId) { $category = $this->_categoryFactory->create()->load($categoryId); /* @var $category \Magento\Catalog\Model\Category */ if (!$this->_catalogCategory->canShow($category)) { return ''; } return $category->getCategoryUrl(); } return ''; }
/** * Add meta information from product to head block * * @return \Magento\Catalog\Block\Product\View */ protected function _prepareLayout() { $this->getLayout()->createBlock('Magento\\Catalog\\Block\\Breadcrumbs'); $product = $this->getProduct(); if (!$product) { return parent::_prepareLayout(); } $headBlock = $this->getLayout()->getBlock('head'); if ($headBlock) { $title = $product->getMetaTitle(); if ($title) { $headBlock->setTitle($title); } $keyword = $product->getMetaKeyword(); $currentCategory = $this->_coreRegistry->registry('current_category'); if ($keyword) { $headBlock->setKeywords($keyword); } elseif ($currentCategory) { $headBlock->setKeywords($product->getName()); } $description = $product->getMetaDescription(); if ($description) { $headBlock->setDescription($description); } else { $headBlock->setDescription($this->string->substr($product->getDescription(), 0, 255)); } //@todo: move canonical link to separate block $childBlockName = 'magento-page-head-product-canonical-link'; if ($this->_productHelper->canUseCanonicalTag() && !$headBlock->getChildBlock($childBlockName)) { $params = array('_ignore_category' => true); $headBlock->addChild($childBlockName, 'Magento\\Theme\\Block\\Html\\Head\\Link', array('url' => $product->getUrlModel()->getUrl($product, $params), 'properties' => array('attributes' => array('rel' => 'canonical')))); } } $pageMainTitle = $this->getLayout()->getBlock('page.main.title'); if ($pageMainTitle) { $pageMainTitle->setPageTitle($product->getName()); } return parent::_prepareLayout(); }
/** * @param \PHPUnit_Framework_MockObject_MockObject|DefaultType $group * @param \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Product\Option $option * @param \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Object $buyRequest * @param \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Product $product */ protected function parentClass($group, $option, $buyRequest, $product) { $group->expects($this->once())->method('setOption')->willReturnSelf(); $group->expects($this->once())->method('setProduct')->willReturnSelf(); $group->expects($this->once())->method('setRequest')->willReturnSelf(); $group->expects($this->once())->method('setProcessMode')->willReturnSelf(); $group->expects($this->once())->method('validateUserValue')->willReturnSelf(); $group->expects($this->once())->method('prepareForCart')->willReturn('someString'); $option->expects($this->once())->method('getType'); $option->expects($this->once())->method('groupFactory')->willReturn($group); $option->expects($this->at(0))->method('getId')->willReturn(333); $buyRequest->expects($this->once())->method('getData'); $buyRequest->expects($this->once())->method('getOptions'); $buyRequest->expects($this->once())->method('getSuperProductConfig')->willReturn([]); $buyRequest->expects($this->any())->method('unsetData')->willReturnSelf(); $buyRequest->expects($this->any())->method('getQty'); $product->expects($this->once())->method('getOptions')->willReturn([$option]); $product->expects($this->once())->method('prepareCustomOptions'); $product->expects($this->any())->method('addCustomOption')->willReturnSelf(); $product->expects($this->any())->method('setCartQty')->willReturnSelf(); $product->expects($this->once())->method('setQty'); $this->catalogProduct->expects($this->once())->method('getSkipSaleableCheck')->willReturn(false); }
/** * Prepares and render result of composite product configuration request * * The $configureResult variable holds either: * - 'ok' = true, and 'product_id', 'buy_request', 'current_store_id', 'current_customer_id' * - 'error' = true, and 'message' to show * * @param \Magento\Framework\Object $configureResult * @return void */ public function renderConfigureResult(\Magento\Framework\Object $configureResult) { try { if (!$configureResult->getOk()) { throw new \Magento\Framework\Model\Exception($configureResult->getMessage()); } $currentStoreId = (int) $configureResult->getCurrentStoreId(); if (!$currentStoreId) { $currentStoreId = $this->_storeManager->getStore()->getId(); } $product = $this->_productFactory->create()->setStoreId($currentStoreId)->load($configureResult->getProductId()); if (!$product->getId()) { throw new \Magento\Framework\Model\Exception(__('The product is not loaded.')); } $this->_coreRegistry->register('current_product', $product); $this->_coreRegistry->register('product', $product); // Register customer we're working with $customerId = (int) $configureResult->getCurrentCustomerId(); // TODO: Remove the customer model from the registry once all readers are refactored $customerModel = $this->_converter->loadCustomerModel($customerId); $this->_coreRegistry->register(RegistryConstants::CURRENT_CUSTOMER, $customerModel); $this->_coreRegistry->register(RegistryConstants::CURRENT_CUSTOMER_ID, $customerId); // Prepare buy request values $buyRequest = $configureResult->getBuyRequest(); if ($buyRequest) { $this->_catalogProduct->prepareProductOptions($product, $buyRequest); } $isOk = true; $productType = $product->getTypeId(); } catch (\Exception $e) { $isOk = false; $productType = null; $this->_coreRegistry->register('composite_configure_result_error_message', $e->getMessage()); } $this->_initConfigureResultLayout($isOk, $productType); $this->_view->renderLayout(); }
/** * Render grid row * * @param \Magento\Framework\DataObject $row * @return string */ public function render(\Magento\Framework\DataObject $row) { $imageUrl = $row->getImage() && $row->getImage() != 'no_selection' ? $this->escapeHtml($this->_productHelper->getImageUrl($row)) : ''; return $this->_getValue($row) . '<input type="hidden" data-role="image-url" value="' . $imageUrl . '"/>'; }
/** * Updates quote item with new configuration * * $params sets how current item configuration must be taken into account and additional options. * It's passed to \Magento\Catalog\Helper\Product->addParamsToBuyRequest() to compose resulting buyRequest. * * Basically it can hold * - 'current_config', \Magento\Framework\Object or array - current buyRequest that configures product in this item, * used to restore currently attached files * - 'files_prefix': string[a-z0-9_] - prefix that was added at frontend to names of file options (file inputs), * so they won't intersect with other submitted options * * For more options see \Magento\Catalog\Helper\Product->addParamsToBuyRequest() * * @param int $itemId * @param \Magento\Framework\Object $buyRequest * @param null|array|\Magento\Framework\Object $params * @return \Magento\Quote\Model\Quote\Item * @throws \Magento\Framework\Exception\LocalizedException * * @see \Magento\Catalog\Helper\Product::addParamsToBuyRequest() * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function updateItem($itemId, $buyRequest, $params = null) { $item = $this->getItemById($itemId); if (!$item) { throw new \Magento\Framework\Exception\LocalizedException(__('This is the wrong quote item id to update configuration.')); } $productId = $item->getProduct()->getId(); //We need to create new clear product instance with same $productId //to set new option values from $buyRequest $product = clone $this->productRepository->getById($productId, false, $this->getStore()->getId()); if (!$params) { $params = new \Magento\Framework\Object(); } elseif (is_array($params)) { $params = new \Magento\Framework\Object($params); } $params->setCurrentConfig($item->getBuyRequest()); $buyRequest = $this->_catalogProduct->addParamsToBuyRequest($buyRequest, $params); $buyRequest->setResetCount(true); $resultItem = $this->addProduct($product, $buyRequest); if (is_string($resultItem)) { throw new \Magento\Framework\Exception\LocalizedException(__($resultItem)); } if ($resultItem->getParentItem()) { $resultItem = $resultItem->getParentItem(); } if ($resultItem->getId() != $itemId) { /** * Product configuration didn't stick to original quote item * It either has same configuration as some other quote item's product or completely new configuration */ $this->removeItem($itemId); $items = $this->getAllItems(); foreach ($items as $item) { if ($item->getProductId() == $productId && $item->getId() != $resultItem->getId()) { if ($resultItem->compare($item)) { // Product configuration is same as in other quote item $resultItem->setQty($resultItem->getQty() + $item->getQty()); $this->removeItem($item->getId()); break; } } } } else { $resultItem->setQty($buyRequest->getQty()); } return $resultItem; }
/** * Check whether the product type or stock allows to purchase the product * * @return bool */ public function isAvailable() { return $this->getTypeInstance()->isSalable($this) || $this->_catalogProduct->getSkipSaleableCheck(); }
/** * @return \Magento\Backend\Model\View\Result\Redirect * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function execute() { $data = $this->getRequest()->getPostValue(); $resultRedirect = $this->resultRedirectFactory->create(); if ($data) { $setId = $this->getRequest()->getParam('set'); $attributeSet = null; if (!empty($data['new_attribute_set_name'])) { $name = $this->filterManager->stripTags($data['new_attribute_set_name']); $name = trim($name); try { /** @var $attributeSet \Magento\Eav\Model\Entity\Attribute\Set */ $attributeSet = $this->buildFactory->create()->setEntityTypeId($this->_entityTypeId)->setSkeletonId($setId)->setName($name)->getAttributeSet(); } catch (AlreadyExistsException $alreadyExists) { $this->messageManager->addError(__('An attribute set named \'%1\' already exists.', $name)); $this->messageManager->setAttributeData($data); return $resultRedirect->setPath('catalog/*/edit', ['_current' => true]); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { $this->messageManager->addException($e, __('Something went wrong while saving the attribute.')); } } $redirectBack = $this->getRequest()->getParam('back', false); /* @var $model \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ $model = $this->attributeFactory->create(); $attributeId = $this->getRequest()->getParam('attribute_id'); $attributeCode = $this->getRequest()->getParam('attribute_code'); $frontendLabel = $this->getRequest()->getParam('frontend_label'); $attributeCode = $attributeCode ?: $this->generateCode($frontendLabel[0]); if (strlen($this->getRequest()->getParam('attribute_code')) > 0) { $validatorAttrCode = new \Zend_Validate_Regex(['pattern' => '/^[a-z][a-z_0-9]{0,30}$/']); if (!$validatorAttrCode->isValid($attributeCode)) { $this->messageManager->addError(__('Attribute code "%1" is invalid. Please use only letters (a-z), ' . 'numbers (0-9) or underscore(_) in this field, first character should be a letter.', $attributeCode)); return $resultRedirect->setPath('catalog/*/edit', ['attribute_id' => $attributeId, '_current' => true]); } } $data['attribute_code'] = $attributeCode; //validate frontend_input if (isset($data['frontend_input'])) { /** @var $inputType \Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator */ $inputType = $this->validatorFactory->create(); if (!$inputType->isValid($data['frontend_input'])) { foreach ($inputType->getMessages() as $message) { $this->messageManager->addError($message); } return $resultRedirect->setPath('catalog/*/edit', ['attribute_id' => $attributeId, '_current' => true]); } } if ($attributeId) { $model->load($attributeId); if (!$model->getId()) { $this->messageManager->addError(__('This attribute no longer exists.')); return $resultRedirect->setPath('catalog/*/'); } // entity type check if ($model->getEntityTypeId() != $this->_entityTypeId) { $this->messageManager->addError(__('We can\'t update the attribute.')); $this->_session->setAttributeData($data); return $resultRedirect->setPath('catalog/*/'); } $data['attribute_code'] = $model->getAttributeCode(); $data['is_user_defined'] = $model->getIsUserDefined(); $data['frontend_input'] = $model->getFrontendInput(); } else { /** * @todo add to helper and specify all relations for properties */ $data['source_model'] = $this->productHelper->getAttributeSourceModelByInputType($data['frontend_input']); $data['backend_model'] = $this->productHelper->getAttributeBackendModelByInputType($data['frontend_input']); } $data += ['is_filterable' => 0, 'is_filterable_in_search' => 0, 'apply_to' => []]; if (is_null($model->getIsUserDefined()) || $model->getIsUserDefined() != 0) { $data['backend_type'] = $model->getBackendTypeByInput($data['frontend_input']); } $defaultValueField = $model->getDefaultValueByInput($data['frontend_input']); if ($defaultValueField) { $data['default_value'] = $this->getRequest()->getParam($defaultValueField); } if (!$model->getIsUserDefined() && $model->getId()) { // Unset attribute field for system attributes unset($data['apply_to']); } $model->addData($data); if (!$attributeId) { $model->setEntityTypeId($this->_entityTypeId); $model->setIsUserDefined(1); } $groupCode = $this->getRequest()->getParam('group'); if ($setId && $groupCode) { // For creating product attribute on product page we need specify attribute set and group $attributeSetId = $attributeSet ? $attributeSet->getId() : $setId; $groupCollection = $attributeSet ? $attributeSet->getGroups() : $this->groupCollectionFactory->create()->setAttributeSetFilter($attributeSetId)->load(); foreach ($groupCollection as $group) { if ($group->getAttributeGroupCode() == $groupCode) { $attributeGroupId = $group->getAttributeGroupId(); break; } } $model->setAttributeSetId($attributeSetId); $model->setAttributeGroupId($attributeGroupId); } try { $model->save(); $this->messageManager->addSuccess(__('You saved the product attribute.')); $this->_attributeLabelCache->clean(); $this->_session->setAttributeData(false); if ($this->getRequest()->getParam('popup')) { $requestParams = ['attributeId' => $this->getRequest()->getParam('product'), 'attribute' => $model->getId(), '_current' => true, 'product_tab' => $this->getRequest()->getParam('product_tab')]; if (!is_null($attributeSet)) { $requestParams['new_attribute_set_id'] = $attributeSet->getId(); } $resultRedirect->setPath('catalog/product/addAttribute', $requestParams); } elseif ($redirectBack) { $resultRedirect->setPath('catalog/*/edit', ['attribute_id' => $model->getId(), '_current' => true]); } else { $resultRedirect->setPath('catalog/*/'); } return $resultRedirect; } catch (\Exception $e) { $this->messageManager->addError($e->getMessage()); $this->_session->setAttributeData($data); return $resultRedirect->setPath('catalog/*/edit', ['attribute_id' => $attributeId, '_current' => true]); } } return $resultRedirect->setPath('catalog/*/'); }
/** * Retrieve available placeholders * * @return array */ public function getAttributesAllowedForAutogeneration() { return $this->_productHelper->getAttributesAllowedForAutogeneration(); }
/** * @param $productChanged * @param $isScheduled * @param $productFlatCount * @param $categoryIndexerCount * * @dataProvider getProductReindexProvider */ public function testReindex($productChanged, $isScheduled, $productFlatCount, $categoryIndexerCount) { $this->model->setData('entity_id', 1); $this->_catalogProduct->expects($this->once())->method('isDataForProductCategoryIndexerWasChanged')->willReturn($productChanged); if ($productChanged) { $this->indexerRegistryMock->expects($this->exactly($productFlatCount))->method('get')->with(\Magento\Catalog\Model\Indexer\Product\Category::INDEXER_ID)->will($this->returnValue($this->categoryIndexerMock)); $this->categoryIndexerMock->expects($this->any())->method('isScheduled')->will($this->returnValue($isScheduled)); $this->categoryIndexerMock->expects($this->exactly($categoryIndexerCount))->method('reindexRow'); } $this->productFlatProcessor->expects($this->exactly($productFlatCount))->method('reindexRow'); $this->model->reindex(); }
/** * @param Action\Context $context * @param \Magento\Catalog\Helper\Product $productHelper */ public function __construct(Action\Context $context, \Magento\Catalog\Helper\Product $productHelper) { parent::__construct($context); $productHelper->setSkipSaleableCheck(true); }
/** * @param mixed $data * @param boolean $result * @dataProvider getData */ public function testIsDataForPriceIndexerWasChanged($data, $result) { $this->assertEquals($this->_productHelper->isDataForPriceIndexerWasChanged($data), $result); }