Skip to content

Commit

Permalink
ENGCOM-5836: Allow construction of products with custom_attributes in…
Browse files Browse the repository at this point in the history
… $data #24460
  • Loading branch information
lenaorobei authored Feb 4, 2020
2 parents ebe81d8 + 94c40c9 commit 3bd07a1
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 17 deletions.
10 changes: 7 additions & 3 deletions app/code/Magento/Catalog/Model/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,9 @@ public function __construct(
$this->mediaGalleryEntryConverterPool = $mediaGalleryEntryConverterPool;
$this->dataObjectHelper = $dataObjectHelper;
$this->joinProcessor = $joinProcessor;
$this->eavConfig = $config ?? ObjectManager::getInstance()->get(\Magento\Eav\Model\Config::class);
$this->filterCustomAttribute = $filterCustomAttribute
?? ObjectManager::getInstance()->get(FilterProductCustomAttribute::class);
parent::__construct(
$context,
$registry,
Expand All @@ -470,9 +473,6 @@ public function __construct(
$resourceCollection,
$data
);
$this->eavConfig = $config ?? ObjectManager::getInstance()->get(\Magento\Eav\Model\Config::class);
$this->filterCustomAttribute = $filterCustomAttribute
?? ObjectManager::getInstance()->get(FilterProductCustomAttribute::class);
}

/**
Expand Down Expand Up @@ -2160,6 +2160,7 @@ public function reset()
*/
public function getCacheIdTags()
{
// phpstan:ignore
$tags = parent::getCacheIdTags();
$affectedCategoryIds = $this->getAffectedCategoryIds();
if (!$affectedCategoryIds) {
Expand Down Expand Up @@ -2340,6 +2341,7 @@ public function isDisabled()
public function getImage()
{
$this->getTypeInstance()->setImageFromChildProduct($this);
// phpstan:ignore
return parent::getImage();
}

Expand Down Expand Up @@ -2403,6 +2405,7 @@ public function reloadPriceInfo()
}
}

// phpcs:disable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames
/**
* Return Data Object data in array format.
*
Expand All @@ -2411,6 +2414,7 @@ public function reloadPriceInfo()
*/
public function __toArray()
{
// phpcs:enable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames
$data = $this->_data;
$hasToArray = function ($model) {
return is_object($model) && method_exists($model, '__toArray') && is_callable([$model, '__toArray']);
Expand Down
31 changes: 28 additions & 3 deletions app/code/Magento/Customer/Model/Address/AbstractAddress.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,13 @@ public function setData($key, $value = null)
$key = $this->_implodeArrayField($key);
} elseif (is_array($value) && $this->isAddressMultilineAttribute($key)) {
$value = $this->_implodeArrayValues($value);
} elseif (self::CUSTOM_ATTRIBUTES === $key && is_array($value)) {
foreach ($value as &$attribute) {
$attribute = is_array($attribute) ? $attribute : $attribute->__toArray();
$attribute = $this->processCustomAttribute($attribute);
}
}

return parent::setData($key, $value);
}

Expand Down Expand Up @@ -637,8 +643,8 @@ public function unsRegion()
* Is company required
*
* @return bool
* @since 100.2.0
* @throws \Magento\Framework\Exception\LocalizedException
* @since 100.2.0
*/
protected function isCompanyRequired()
{
Expand All @@ -649,8 +655,8 @@ protected function isCompanyRequired()
* Is telephone required
*
* @return bool
* @since 100.2.0
* @throws \Magento\Framework\Exception\LocalizedException
* @since 100.2.0
*/
protected function isTelephoneRequired()
{
Expand All @@ -661,11 +667,30 @@ protected function isTelephoneRequired()
* Is fax required
*
* @return bool
* @since 100.2.0
* @throws \Magento\Framework\Exception\LocalizedException
* @since 100.2.0
*/
protected function isFaxRequired()
{
return ($this->_eavConfig->getAttribute('customer_address', 'fax')->getIsRequired());
}

/**
* Unify attribute format.
*
* @param array $attribute
* @return array
*/
private function processCustomAttribute(array $attribute): array
{
if (isset($attribute['attribute_code']) &&
isset($attribute['value']) &&
is_array($attribute['value']) &&
$this->isAddressMultilineAttribute($attribute['attribute_code'])
) {
$attribute['value'] = $this->_implodeArrayValues($attribute['value']);
}

return $attribute;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

namespace Magento\Catalog\Model;

use Magento\Eav\Model\Config as EavConfig;
use Magento\Catalog\Model\Product;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\TestFramework\ObjectManager;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Framework\ObjectManagerInterface;
Expand Down Expand Up @@ -331,9 +333,9 @@ public function testIsSalable()
$this->_model = $this->productRepository->get('simple');

// fixture
$this->assertTrue((bool)$this->_model->isSalable());
$this->assertTrue((bool)$this->_model->isSaleable());
$this->assertTrue((bool)$this->_model->isAvailable());
$this->assertTrue((bool) $this->_model->isSalable());
$this->assertTrue((bool) $this->_model->isSaleable());
$this->assertTrue((bool) $this->_model->isAvailable());
$this->assertTrue($this->_model->isInStock());
}

Expand All @@ -350,9 +352,9 @@ public function testIsNotSalableWhenStatusDisabled()
$this->_model = $this->productRepository->get('simple');

$this->_model->setStatus(0);
$this->assertFalse((bool)$this->_model->isSalable());
$this->assertFalse((bool)$this->_model->isSaleable());
$this->assertFalse((bool)$this->_model->isAvailable());
$this->assertFalse((bool) $this->_model->isSalable());
$this->assertFalse((bool) $this->_model->isSaleable());
$this->assertFalse((bool) $this->_model->isAvailable());
$this->assertFalse($this->_model->isInStock());
}

Expand Down Expand Up @@ -631,7 +633,7 @@ public function testGetOptions()
continue;
}
foreach ($option->getValues() as $value) {
$this->assertEquals($expectedValue[$value->getSku()], (float)$value->getPrice());
$this->assertEquals($expectedValue[$value->getSku()], (float) $value->getPrice());
}
}
}
Expand Down Expand Up @@ -723,4 +725,40 @@ public function productWithBackordersDataProvider(): array
[1, 1, true],
];
}

public function testConstructionWithCustomAttributesMapInData()
{
$data = [
'custom_attributes' => [
'tax_class_id' => '3',
'category_ids' => '1,2'
],
];

/** @var Product $product */
$product = ObjectManager::getInstance()->create(Product::class, ['data' => $data]);
$this->assertSame($product->getCustomAttribute('tax_class_id')->getValue(), '3');
$this->assertSame($product->getCustomAttribute('category_ids')->getValue(), '1,2');
}

public function testConstructionWithCustomAttributesArrayInData()
{
$data = [
'custom_attributes' => [
[
'attribute_code' => 'tax_class_id',
'value' => '3'
],
[
'attribute_code' => 'category_ids',
'value' => '1,2'
]
],
];

/** @var Product $product */
$product = ObjectManager::getInstance()->create(Product::class, ['data' => $data]);
$this->assertSame($product->getCustomAttribute('tax_class_id')->getValue(), '3');
$this->assertSame($product->getCustomAttribute('category_ids')->getValue(), '1,2');
}
}
31 changes: 27 additions & 4 deletions lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,28 @@ public function __construct(
}
}

/**
* Convert the custom attributes array format to map format
*
* The method \Magento\Framework\Reflection\DataObjectProcessor::buildOutputDataArray generates a custom_attributes
* array representation where each custom attribute is a sub-array with a `attribute_code and value key.
* This method maps such an array to the plain code => value map format exprected by filterCustomAttributes
*
* @param array[] $customAttributesData
* @return array
*/
private function flattenCustomAttributesArrayToMap(array $customAttributesData): array
{
return array_reduce(
$customAttributesData,
function (array $acc, array $customAttribute): array {
$acc[$customAttribute['attribute_code']] = $customAttribute['value'];
return $acc;
},
[]
);
}

/**
* Verify custom attributes set on $data and unset if not a valid custom attribute
*
Expand All @@ -85,9 +107,12 @@ protected function filterCustomAttributes($data)
if (empty($data[self::CUSTOM_ATTRIBUTES])) {
return $data;
}
$customAttributesCodes = $this->getCustomAttributesCodes();
if (isset($data[self::CUSTOM_ATTRIBUTES][0])) {
$data[self::CUSTOM_ATTRIBUTES] = $this->flattenCustomAttributesArrayToMap($data[self::CUSTOM_ATTRIBUTES]);
}
$customAttributesCodes = $this->getCustomAttributesCodes();
$data[self::CUSTOM_ATTRIBUTES] = array_intersect_key(
(array)$data[self::CUSTOM_ATTRIBUTES],
(array) $data[self::CUSTOM_ATTRIBUTES],
array_flip($customAttributesCodes)
);
foreach ($data[self::CUSTOM_ATTRIBUTES] as $code => $value) {
Expand All @@ -102,8 +127,6 @@ protected function filterCustomAttributes($data)

/**
* Initialize customAttributes based on existing data
*
* @return $this
*/
protected function initializeCustomAttributes()
{
Expand Down

0 comments on commit 3bd07a1

Please sign in to comment.