diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php index af10eeea42fd3..473f1aea33618 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php @@ -63,7 +63,8 @@ protected function setUp() 'getAttributes', 'getStore', 'getAttributeDefaultValue', - 'getExistsStoreValueFlag' + 'getExistsStoreValueFlag', + 'isLockedAttribute' ])->getMockForAbstractClass(); $this->storeMock = $this->getMockBuilder(StoreInterface::class) ->setMethods(['load', 'getId', 'getConfig']) @@ -81,9 +82,6 @@ protected function setUp() $this->arrayManagerMock->expects($this->any()) ->method('set') ->willReturnArgument(1); - $this->arrayManagerMock->expects($this->any()) - ->method('merge') - ->willReturnArgument(1); $this->arrayManagerMock->expects($this->any()) ->method('remove') ->willReturnArgument(1); diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AttributeSetTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AttributeSetTest.php index c22dde0b456ac..5fc6231b03735 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AttributeSetTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AttributeSetTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Catalog\Test\Unit\Ui\DataProvider\Product\Form\Modifier; +use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AttributeSet; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\Collection; @@ -84,7 +85,30 @@ protected function createModel() public function testModifyMeta() { - $this->assertNotEmpty($this->getModel()->modifyMeta(['test_group' => []])); + $modifyMeta = $this->getModel()->modifyMeta(['test_group' => []]); + $this->assertNotEmpty($modifyMeta); + } + + /** + * @param bool $locked + * @dataProvider modifyMetaLockedDataProvider + */ + public function testModifyMetaLocked($locked) + { + $this->productMock->expects($this->any()) + ->method('isLockedAttribute') + ->willReturn($locked); + $modifyMeta = $this->getModel()->modifyMeta([AbstractModifier::DEFAULT_GENERAL_PANEL => []]); + $children = $modifyMeta[AbstractModifier::DEFAULT_GENERAL_PANEL]['children']; + $this->assertEquals( + $locked, + $children['attribute_set_id']['arguments']['data']['config']['disabled'] + ); + } + + public function modifyMetaLockedDataProvider() + { + return [[true], [false]]; } public function testModifyMetaToBeEmpty() diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php index 4daff7e7930e3..5f5913c20209a 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php @@ -114,6 +114,44 @@ public function testModifyMeta() $this->assertArrayHasKey($groupCode, $this->getModel()->modifyMeta($meta)); } + /** + * @param bool $locked + * @dataProvider modifyMetaLockedDataProvider + */ + public function testModifyMetaLocked($locked) + { + $groupCode = 'test_group_code'; + $meta = [ + $groupCode => [ + 'children' => [ + 'category_ids' => [ + 'sortOrder' => 10, + ], + ], + ], + ]; + + $this->arrayManagerMock->expects($this->any()) + ->method('findPath') + ->willReturn('path'); + + $this->productMock->expects($this->any()) + ->method('isLockedAttribute') + ->willReturn($locked); + + $this->arrayManagerMock->expects($this->any()) + ->method('merge') + ->willReturnArgument(2); + + $modifyMeta = $this->createModel()->modifyMeta($meta); + $this->assertEquals($locked, $modifyMeta['arguments']['data']['config']['disabled']); + } + + public function modifyMetaLockedDataProvider() + { + return [[true], [false]]; + } + public function testModifyMetaWithCaching() { $this->arrayManagerMock->expects($this->exactly(2)) diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php index 0426e389d9aeb..22bb712d42f0f 100755 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php @@ -462,7 +462,7 @@ public function testModifyData() * @param bool $productRequired * @param string|null $attrValue * @param array $expected - * @return void + * @param bool $locked * @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::isProductExists * @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::setupAttributeMeta * @dataProvider setupAttributeMetaDataProvider @@ -471,7 +471,8 @@ public function testSetupAttributeMetaDefaultAttribute( $productId, bool $productRequired, $attrValue, - array $expected + array $expected, + $locked = false ) : void { $configPath = 'arguments/data/config'; $groupCode = 'product-details'; @@ -492,6 +493,7 @@ public function testSetupAttributeMetaDefaultAttribute( ]; $this->productMock->method('getId')->willReturn($productId); + $this->productMock->expects($this->any())->method('isLockedAttribute')->willReturn($locked); $this->productAttributeMock->method('getIsRequired')->willReturn($productRequired); $this->productAttributeMock->method('getDefaultValue')->willReturn('required_value'); $this->productAttributeMock->method('getAttributeCode')->willReturn('code'); @@ -520,14 +522,14 @@ public function testSetupAttributeMetaDefaultAttribute( ) ->willReturn($expected); - $this->arrayManagerMock->expects($this->once()) + $this->arrayManagerMock->expects($this->any()) ->method('merge') ->with( $this->anything(), $this->anything(), $this->callback( function ($value) use ($attributeOptionsExpected) { - return $value['options'] === $attributeOptionsExpected; + return isset($value['options']) ? $value['options'] === $attributeOptionsExpected : true; } ) ) @@ -544,6 +546,7 @@ function ($value) use ($attributeOptionsExpected) { /** * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function setupAttributeMetaDataProvider() { @@ -567,6 +570,26 @@ public function setupAttributeMetaDataProvider() 'sortOrder' => 0, ], ], + 'default_null_prod_not_new_locked_and_required' => [ + 'productId' => 1, + 'productRequired' => true, + 'attrValue' => 'val', + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => true, + 'notice' => null, + 'default' => null, + 'label' => new Phrase(null), + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0, + ], + 'locked' => true, + ], 'default_null_prod_not_new_and_not_required' => [ 'productId' => 1, 'productRequired' => false, @@ -605,6 +628,26 @@ public function setupAttributeMetaDataProvider() 'sortOrder' => 0, ], ], + 'default_null_prod_new_locked_and_not_required' => [ + 'productId' => null, + 'productRequired' => false, + 'attrValue' => null, + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => false, + 'notice' => null, + 'default' => 'required_value', + 'label' => new Phrase(null), + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0, + ], + 'locked' => true, + ], 'default_null_prod_new_and_required' => [ 'productId' => null, 'productRequired' => false, diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php index 78502ae297b52..a9d717db7b7f9 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php @@ -60,6 +60,9 @@ protected function createModel() public function testModifyMeta() { + $this->arrayManagerMock->expects($this->any()) + ->method('merge') + ->willReturnArgument(2); $this->assertNotEmpty($this->getModel()->modifyMeta([ 'first_panel_code' => [ 'arguments' => [ diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ScheduleDesignUpdateTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ScheduleDesignUpdateTest.php index d4d4136bf4157..783c6247b9df3 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ScheduleDesignUpdateTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ScheduleDesignUpdateTest.php @@ -24,6 +24,9 @@ protected function createModel() public function testModifyMeta() { + $this->arrayManagerMock->expects($this->any()) + ->method('merge') + ->willReturnArgument(1); $this->assertSame([], $this->getModel()->modifyMeta([])); } diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/WebsitesTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/WebsitesTest.php index 997b66861c21b..c3096770729a6 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/WebsitesTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/WebsitesTest.php @@ -76,7 +76,10 @@ class WebsitesTest extends AbstractModifierTest protected function setUp() { - $this->objectManager = new ObjectManager($this); + parent::setUp(); + $this->productMock->expects($this->any()) + ->method('getId') + ->willReturn(self::PRODUCT_ID); $this->assignedWebsites = [self::SECOND_WEBSITE_ID]; $this->websiteMock = $this->getMockBuilder(\Magento\Store\Model\Website::class) ->setMethods(['getId', 'getName']) @@ -101,15 +104,9 @@ protected function setUp() $this->storeRepositoryMock = $this->getMockBuilder(\Magento\Store\Api\StoreRepositoryInterface::class) ->setMethods(['getList']) ->getMockForAbstractClass(); - $this->locatorMock = $this->getMockBuilder(\Magento\Catalog\Model\Locator\LocatorInterface::class) - ->setMethods(['getProduct', 'getWebsiteIds']) - ->getMockForAbstractClass(); $this->productMock = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class) ->setMethods(['getId']) ->getMockForAbstractClass(); - $this->locatorMock->expects($this->any()) - ->method('getProduct') - ->willReturn($this->productMock); $this->locatorMock->expects($this->any()) ->method('getWebsiteIds') ->willReturn($this->assignedWebsites); @@ -148,9 +145,6 @@ protected function setUp() $this->storeRepositoryMock->expects($this->any()) ->method('getList') ->willReturn([$this->storeViewMock]); - $this->productMock->expects($this->any()) - ->method('getId') - ->willReturn(self::PRODUCT_ID); $this->secondWebsiteMock->expects($this->any()) ->method('getId') ->willReturn($this->assignedWebsites[0]); diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php index 63b7f5faa6562..336aeffa10584 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php @@ -432,7 +432,8 @@ private function getTierPriceStructure($tierPricePath) 'dndConfig' => [ 'enabled' => false, ], - 'disabled' => false, + 'disabled' => + $this->arrayManager->get($tierPricePath . '/arguments/data/config/disabled', $this->meta), 'required' => false, 'sortOrder' => $this->arrayManager->get($tierPricePath . '/arguments/data/config/sortOrder', $this->meta), diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet.php index a1aacc91f2e47..0733d21bf47d7 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AttributeSet.php @@ -108,6 +108,7 @@ public function modifyMeta(array $meta) self::ATTRIBUTE_SET_FIELD_ORDER ), 'multiple' => false, + 'disabled' => $this->locator->getProduct()->isLockedAttribute('attribute_set_id'), ]; } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php index 7456c1bfef91f..ed737df708ab8 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php @@ -228,6 +228,7 @@ protected function customizeCategoriesField(array $meta) 'componentType' => 'container', 'component' => 'Magento_Ui/js/form/components/group', 'scopeLabel' => __('[GLOBAL]'), + 'disabled' => $this->locator->getProduct()->isLockedAttribute($fieldCode), ], ], ], diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 0e6f17d761bc3..7cd81419c0347 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -41,6 +41,7 @@ * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @since 101.0.0 */ class Eav extends AbstractModifier @@ -593,6 +594,7 @@ private function isProductExists() public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupCode, $sortOrder) { $configPath = ltrim(static::META_CONFIG_PATH, ArrayManager::DEFAULT_PATH_DELIMITER); + $attributeCode = $attribute->getAttributeCode(); $meta = $this->arrayManager->set($configPath, [], [ 'dataType' => $attribute->getFrontendInput(), 'formElement' => $this->getFormElementsMapValue($attribute->getFrontendInput()), @@ -601,7 +603,7 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC 'notice' => $attribute->getNote() === null ? null : __($attribute->getNote()), 'default' => (!$this->isProductExists()) ? $this->getAttributeDefaultValue($attribute) : null, 'label' => __($attribute->getDefaultFrontendLabel()), - 'code' => $attribute->getAttributeCode(), + 'code' => $attributeCode, 'source' => $groupCode, 'scopeLabel' => $this->getScopeLabel($attribute), 'globalScope' => $this->isScopeGlobal($attribute), @@ -631,7 +633,9 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC ]); } - if (in_array($attribute->getAttributeCode(), $this->attributesToDisable)) { + $product = $this->locator->getProduct(); + if (in_array($attributeCode, $this->attributesToDisable) + || $product->isLockedAttribute($attributeCode)) { $meta = $this->arrayManager->merge($configPath, $meta, [ 'disabled' => true, ]); diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php index 279b905577689..98de8ea347671 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php @@ -203,7 +203,7 @@ protected function customizeStatusField(array $meta) protected function customizeWeightField(array $meta) { $weightPath = $this->arrayManager->findPath(ProductAttributeInterface::CODE_WEIGHT, $meta, null, 'children'); - + $disabled = $this->arrayManager->get($weightPath . '/arguments/data/config/disabled', $meta); if ($weightPath) { $meta = $this->arrayManager->merge( $weightPath . static::META_CONFIG_PATH, @@ -215,7 +215,7 @@ protected function customizeWeightField(array $meta) ], 'additionalClasses' => 'admin__field-small', 'addafter' => $this->locator->getStore()->getConfig('general/locale/weight_unit'), - 'imports' => [ + 'imports' => $disabled ? [] : [ 'disabled' => '!${$.provider}:' . self::DATA_SCOPE_PRODUCT . '.product_has_weight:value' ] @@ -255,6 +255,7 @@ protected function customizeWeightField(array $meta) ], ], 'value' => (int)$this->locator->getProduct()->getTypeInstance()->hasWeight(), + 'disabled' => $disabled, ] ); } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php index 298da3d5cd6f2..bab36ce5fc4d8 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Websites.php @@ -135,7 +135,6 @@ public function modifyMeta(array $meta) 'collapsible' => true, 'componentType' => Form\Fieldset::NAME, 'dataScope' => self::DATA_SCOPE_PRODUCT, - 'disabled' => false, 'sortOrder' => $this->getNextGroupSortOrder( $meta, 'search-engine-optimization', @@ -196,6 +195,7 @@ protected function getFieldsForFieldset() 'false' => '0', ], 'value' => $isChecked ? (string)$website['id'] : '0', + 'disabled' => $this->locator->getProduct()->isLockedAttribute('website_ids'), ], ], ], diff --git a/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventory.php b/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventory.php index d15f17530ffbc..7386f133b569a 100644 --- a/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventory.php +++ b/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventory.php @@ -223,6 +223,7 @@ private function prepareMeta() $this->arrayManager->slicePath($pathField, 0, -2) . '/arguments/data/config/sortOrder', $this->meta ) - 1, + 'disabled' => $this->locator->getProduct()->isLockedAttribute($fieldCode), ]; $qty['arguments']['data']['config'] = [ 'component' => 'Magento_CatalogInventory/js/components/qty-validator-changer', diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php index e2e9fe9b2b1f9..659f7346faba4 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Ui/DataProvider/Product/Form/Modifier/CustomOptionsTest.php @@ -10,6 +10,14 @@ class CustomOptionsTest extends AbstractModifierTest { + protected function setUp() + { + parent::setUp(); + $this->arrayManagerMock->expects($this->any()) + ->method('merge') + ->willReturnArgument(1); + } + /** * {@inheritdoc} */ diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserData.xml index 65ddfa7bb9559..c15e6004ed64a 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserData.xml @@ -18,5 +18,16 @@ en_US true 123123q + + + restrictedWebUser + restricted + webUser + restrictedWebUser@example.com + 123123q + 123123q + en_US + true + 123123q diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/User/Section/AdminEditRoleInfoSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/User/Section/AdminEditRoleInfoSection.xml index 3e5b4ac6ecc88..69d1fdea9cb51 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/User/Section/AdminEditRoleInfoSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/User/Section/AdminEditRoleInfoSection.xml @@ -12,6 +12,10 @@ + + + + diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php index fd0f6e98840c9..22bb76ca9222d 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php @@ -6,6 +6,7 @@ namespace Magento\Catalog\Ui\DataProvider\Product\Form\Modifier; +use Magento\Catalog\Model\Product; use Magento\TestFramework\Helper\CacheCleaner; /** @@ -29,6 +30,8 @@ protected function setUp() $store = $objectManager->create(\Magento\Store\Model\Store::class); $store->load('admin'); $registry->register('current_store', $store); + $product = $objectManager->create(Product::class); + $registry->register('current_product', $product); $this->object = $objectManager->create(Categories::class); }