/** * ES field used in attribute autocomplete. * * @param \Magento\Catalog\Model\ResourceModel\Product\Attribute $attribute Attribute. * * @return string */ public function getAttributeAutocompleteField(\Magento\Catalog\Api\Data\ProductAttributeInterface $attribute) { $fieldName = $attribute->getAttributeCode(); if ($attribute->usesSource()) { $fieldName = $this->mappingHelper->getOptionTextFieldName($fieldName); } return $fieldName; }
/** * {@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); return $attribute; }
/** * Build validation rules * * @param ProductAttributeInterface $attribute * @param array $data * @return array */ public function build(ProductAttributeInterface $attribute, array $data) { $rules = []; if (!empty($data['required'])) { $rules['required-entry'] = true; } if ($attribute->getFrontendInput() === 'price') { $rules['validate-zero-or-greater'] = true; } $validationClasses = explode(' ', $attribute->getFrontendClass()); foreach ($validationClasses as $class) { if (preg_match('/^maximum-length-(\\d+)$/', $class, $matches)) { $rules = array_merge($rules, ['max_text_length' => $matches[1]]); continue; } if (preg_match('/^minimum-length-(\\d+)$/', $class, $matches)) { $rules = array_merge($rules, ['min_text_length' => $matches[1]]); continue; } $rules = $this->mapRules($class, $rules); } return $rules; }
/** * @expectedException \Magento\Framework\Exception\InputException * @expectedExceptionMessage Products "5" and "4" have the same set of attribute values. */ public function testAroundSaveWithLinksWithDuplicateAttributes() { $links = [4, 5]; $attributeCode = 'color'; $attributeId = 23; $this->option->expects(static::once())->method('getAttributeId')->willReturn($attributeId); $this->product->expects(static::once())->method('getTypeId')->willReturn(Configurable::TYPE_CODE); $this->result->expects(static::once())->method('getExtensionAttributes')->willReturn($this->extensionAttributes); $this->extensionAttributes->expects(static::once())->method('getConfigurableProductOptions')->willReturn([$this->option]); $this->extensionAttributes->expects(static::once())->method('getConfigurableProductLinks')->willReturn($links); $this->productAttributeRepository->expects(static::once())->method('get')->willReturn($this->eavAttribute); $this->eavAttribute->expects(static::once())->method('getAttributeCode')->willReturn($attributeCode); $product = $this->getMockBuilder(Product::class)->disableOriginalConstructor()->setMethods(['load', 'getData', '__wakeup'])->getMock(); $this->productFactory->expects(static::exactly(2))->method('create')->willReturn($product); $product->expects(static::exactly(2))->method('load')->willReturnSelf(); $product->expects(static::exactly(4))->method('getData')->with($attributeCode)->willReturn($attributeId); $this->plugin->aroundSave($this->productRepository, $this->closure, $this->product); }
/** * @param \Magento\Catalog\Api\Data\ProductAttributeInterface $attribute * @return string */ protected function getDataType($attribute) { return isset($this->dataTypeMap[$attribute->getFrontendInput()]) ? $this->dataTypeMap[$attribute->getFrontendInput()] : $this->dataTypeMap['default']; }
/** * @param \Magento\Catalog\Api\Data\ProductAttributeInterface $attribute * @return bool */ public function isAttributeApplicable($attribute) { $types = [\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE, \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL, \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE]; return !$attribute->getApplyTo() || count(array_diff($types, $attribute->getApplyTo())) === 0; }
/** * Load attribute model by attribute data object. * * TODO: This method should be eliminated when all missing service methods are implemented * * @param ProductAttributeInterface $attribute * @return EavAttribute */ private function getAttributeModel($attribute) { return $this->eavAttributeFactory->create()->load($attribute->getAttributeId()); }
/** * Generates child products for configurable product * * @param \Magento\Catalog\Api\Data\ProductAttributeInterface $configurableAttribute * @return array * @throws \Exception */ protected function createConfigurableChildren($configurableAttribute) { $availableOptions = $configurableAttribute->getOptions(); /* Not sure why the zero index has no value for all attributes. Maybe will be fixed in next Magento versions */ unset($availableOptions[0]); if (!count($availableOptions) > 0) { throw new \Exception('The selected configurable attribute has no values'); } // Create child simple products $availableProductsCount = $this->getCount() - $this->processedProducts - 1; if ($availableProductsCount >= self::CONFIGURABLE_CHILD_LIMIT) { $childrenLimit = self::CONFIGURABLE_CHILD_LIMIT; } else { $childrenLimit = $availableProductsCount; } if ($childrenLimit > count($availableOptions)) { $childrenLimit = count($availableOptions); } $childrenCount = rand(1, $childrenLimit); $childProductsIds = $configurableOptionsValues = []; for ($optCount = 0; $optCount < $childrenCount; $optCount++) { $product = $this->createSimpleProduct(true, true); $currentOptionId = array_rand($availableOptions); $optValueId = $availableOptions[$currentOptionId]->getValue(); unset($availableOptions[$currentOptionId]); $product->setCustomAttribute($configurableAttribute->getAttributeCode(), $optValueId); $optionValue = $this->optionValue; $optionValue->setValueIndex($optValueId); $configurableOptionsValues[] = $optionValue; $product = $this->productRepository->save($product); $childProductsIds[] = $product->getId(); } return ['child_products_ids' => $childProductsIds, 'configurable_options_values' => $configurableOptionsValues]; }