-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow construction of products with custom_attributes in $data #24407
Conversation
Hi @Vinai. Thank you for your contribution
For more details, please, review the Magento Contributor Guide documentation. |
Nice observation @Vinai! What was the use for |
@orlangur I simply was passing an array created via Also, custom attributes are so much more practical in 95% of all cases compared to extension attributes, they are still extremely common, and should work as expected, even if extension attributes are the recommended way to go. |
oh, that's a bit of shame .) thanks for enforcing this use case with tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
I don't like the unrelated to main changes type-casting-spacing part but we need to enforce and fix it everywhere anyway.
Hi @orlangur, thank you for the review.
|
This patch does two things: 1. Currently it is not possible to pass an array with `custom_attributes` to the `\Magento\Catalog\Model\Product` constructor (it causes a fatal error). The reason is because the `filterCustomAttribute` and `eavConfig` arguments are assigned after the call to `parent::__construct`. However, the properties are used during the `parent::__construct` calls. The flow of execution is as follows: Product::__construct -> Catalog\Model\AbstractModel::__construct Catalog\Model\AbstractModel::__construct -> AbstractExtensibleModel::__construct AbstractExtensibleModel::__construct -> AbstractExtensibleModel::filterCustomAttributes AbstractExtensibleModel::filterCustomAttributes -> AbstractExtensibleModel::getCustomAttributesCodes ...which is overridden by Product::getCustomAttributesCodes getCustomAttributesCodes expectes the `filterCustomAttribute` and `eavConfig` properties to be set if `custom_attributes` are present in `$data`, but they are still null because the `Product::__construct` method has not yet completed. The fix this PR applies is to assign the properties before the call to `parent::__construct`. The bug and fix are covered by the integration test: `\Magento\Catalog\Model\ProductTest::testConstructionWithCustomAttributesMapInData` 2. The method `AbstractExtensibleModel::filterCustomAttribute` expects the `custom_attributes` in `$data` to be a simple map from codes to values, e.g. `['category_ids => '1,2']`. However, the method `\Magento\Framework\Reflection\DataObjectProcessor::buildOutputDataArray` generates a numerically indexed custom attributes array, where each custom attribute is a sub-array with a `attribute_code` and `value` record. This PR allows passing such an `custom_attributes` array into the `Product` model constructor. Currently it would be ignored, but with this patch the code checks if `custom_attributes` is numerically indexed, and if so, flattens the sub-arrays into the expected map format. To illustrate the difference of the `custom_attributes` array formats: Map: [ 'custom_attributes' => [ 'category_ids' => '1,2', 'tax_class_id' => '3', ] ] Numerically indexed array of sub-arrays: [ 'custom_attributes' => [ [ 'attribute_code' => 'category_ids', 'value' => '1,2' ], [ 'attribute_code' => 'tax_class_id', 'value' => '3' ], ] ] This improvement is covered by the integration test `\Magento\Catalog\Model\ProductTest::testConstructionWithCustomAttributesArrayInData`
775f1df
to
19fd9c4
Compare
Note: force pushed a commit that hopefully fixes the static tests. |
@orlangur Only just noticed you already approved the changes, otherwise I wouldn't have pushed commit that hopefully fixes the static tests. |
$websiteStoreIds = array_map(function (int $websiteId): array { | ||
return $this->_storeManager->getWebsite($websiteId)->getStoreIds(); | ||
}, $websiteIds); | ||
$storeIds = array_merge($storeIds, ...$websiteStoreIds); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is only because the static tests complained about the array_merge
in a loop. I didn't write that loop, but I don't mind changing it to get the tests green.
Hi @Vinai, thank you for your contribution! |
I closed this PR accidentally because I deleted the remote branch (typed |
@Vinai when you recreate a branch, reopen is still not available? |
@orlangur No, unfortunately I wasn't able to reopen the original PR. |
Description
This patch does two things:
Currently it is not possible to pass an array with
custom_attributes
to the
\Magento\Catalog\Model\Product
constructor (it causes a fatal error).The reason is because the
filterCustomAttribute
andeavConfig
arguments areassigned after the call to
parent::__construct
.However, the properties are used during the
parent::__construct
calls.The flow of execution is as follows:
Product::__construct
->Catalog\Model\AbstractModel::__construct
Catalog\Model\AbstractModel::__construct
->AbstractExtensibleModel::__construct
AbstractExtensibleModel::__construct
->AbstractExtensibleModel::filterCustomAttributes
AbstractExtensibleModel::filterCustomAttributes
->AbstractExtensibleModel::getCustomAttributesCodes
...which is overridden by
Product::getCustomAttributesCodes
getCustomAttributesCodes
expectes thefilterCustomAttribute
andeavConfig
properties to be set ifcustom_attributes
are present in$data
, but they are still null because theProduct::__construct
method has not yet completed.
The fix this PR applies is to assign the properties before the call to
parent::__construct
.The bug and fix are covered by the integration test:
\Magento\Catalog\Model\ProductTest::testConstructionWithCustomAttributesMapInData
The method
AbstractExtensibleModel::filterCustomAttribute
expects thecustom_attributes
in$data
tobe a simple map from codes to values, e.g.
['category_ids => '1,2']
.However, the method
\Magento\Framework\Reflection\DataObjectProcessor::buildOutputDataArray
generates anumerically indexed custom attributes array, where each custom attribute is a sub-array with a
attribute_code
and
value
record.This PR allows passing such an
custom_attributes
array into theProduct
model constructor.Currently it would be ignored, but with this patch the code checks if
custom_attributes
is numerically indexed,and if so, flattens the sub-arrays into the expected map format.
This improvement is covered by the integration test
\Magento\Catalog\Model\ProductTest::testConstructionWithCustomAttributesArrayInData
To illustrate the difference of the
custom_attributes
array formats:This PR contains no backward incompatible changes.
Manual testing scenarios:
Create a product model instance passing in a
$data
array withcustom_attributes
(any format).An example of this can be seen in the tests in this PR.
Contribution checklist (*)