Skip to content

Commit

Permalink
ENGCOM-5683: #16832 - Reworked query in getAttributeRawValue so that …
Browse files Browse the repository at this point in the history
…it returns a store specific value even if there is no default value #23369

 - Merge Pull Request #23369 from semajeg/magento2:16382-getAttributeRawValue-no-default
 - Merged commits:
   1. 01f1f15
   2. 64184b3
   3. 35c5185
   4. 9ae33c8
   5. 8c4bfa6
   6. 7b0e528
   7. c34f83c
   8. 4d380bf
   9. 540f03e
  • Loading branch information
magento-engcom-team committed Aug 23, 2019
2 parents 484cc98 + 540f03e commit 6093314
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 14 deletions.
43 changes: 29 additions & 14 deletions app/code/Magento/Catalog/Model/ResourceModel/AbstractResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
/**
* Catalog entity abstract model
*
* phpcs:disable Magento2.Classes.AbstractApi
* @api
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
Expand Down Expand Up @@ -468,7 +469,7 @@ protected function _getOrigObject($object)
*
* @param AbstractAttribute $attribute
* @param mixed $value New value of the attribute.
* @param array &$origData
* @param array $origData
* @return bool
*/
protected function _canUpdateAttribute(AbstractAttribute $attribute, $value, array &$origData)
Expand Down Expand Up @@ -560,15 +561,19 @@ public function getAttributeRawValue($entityId, $attribute, $store)
$store = (int) $store;
if ($typedAttributes) {
foreach ($typedAttributes as $table => $_attributes) {
$defaultJoinCondition = [
$connection->quoteInto('default_value.attribute_id IN (?)', array_keys($_attributes)),
"default_value.{$this->getLinkField()} = e.{$this->getLinkField()}",
'default_value.store_id = 0',
];

$select = $connection->select()
->from(['default_value' => $table], ['attribute_id'])
->join(
['e' => $this->getTable($this->getEntityTable())],
'e.' . $this->getLinkField() . ' = ' . 'default_value.' . $this->getLinkField(),
''
)->where('default_value.attribute_id IN (?)', array_keys($_attributes))
->where("e.entity_id = :entity_id")
->where('default_value.store_id = ?', 0);
->from(['e' => $this->getTable($this->getEntityTable())], [])
->joinLeft(
['default_value' => $table],
implode(' AND ', $defaultJoinCondition),
[]
)->where("e.entity_id = :entity_id");

$bind = ['entity_id' => $entityId];

Expand All @@ -578,6 +583,11 @@ public function getAttributeRawValue($entityId, $attribute, $store)
'default_value.value',
'store_value.value'
);
$attributeIdExpr = $connection->getCheckSql(
'store_value.attribute_id IS NULL',
'default_value.attribute_id',
'store_value.attribute_id'
);
$joinCondition = [
$connection->quoteInto('store_value.attribute_id IN (?)', array_keys($_attributes)),
"store_value.{$this->getLinkField()} = e.{$this->getLinkField()}",
Expand All @@ -587,23 +597,28 @@ public function getAttributeRawValue($entityId, $attribute, $store)
$select->joinLeft(
['store_value' => $table],
implode(' AND ', $joinCondition),
['attr_value' => $valueExpr]
['attribute_id' => $attributeIdExpr, 'attr_value' => $valueExpr]
);

$bind['store_id'] = $store;
} else {
$select->columns(['attr_value' => 'value'], 'default_value');
$select->columns(
['attribute_id' => 'attribute_id', 'attr_value' => 'value'],
'default_value'
);
}

$result = $connection->fetchPairs($select, $bind);
foreach ($result as $attrId => $value) {
$attrCode = $typedAttributes[$table][$attrId];
$attributesData[$attrCode] = $value;
if ($attrId !== '') {
$attrCode = $typedAttributes[$table][$attrId];
$attributesData[$attrCode] = $value;
}
}
}
}

if (is_array($attributesData) && sizeof($attributesData) == 1) {
if (is_array($attributesData) && count($attributesData) == 1) {
$attributesData = array_shift($attributesData);
}

Expand Down
91 changes: 91 additions & 0 deletions dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/ProductTest.php
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@
use Magento\Framework\ObjectManagerInterface;
use Magento\TestFramework\Helper\Bootstrap;
use PHPUnit\Framework\TestCase;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\StateException;

/**
* Tests product resource model
*
* @see \Magento\Catalog\Model\ResourceModel\Product
* @see \Magento\Catalog\Model\ResourceModel\AbstractResource
*/
class ProductTest extends TestCase
{
/**
Expand Down Expand Up @@ -53,6 +63,87 @@ public function testGetAttributeRawValue()
self::assertEquals($product->getName(), $actual);
}

/**
* @magentoAppArea adminhtml
* @magentoDataFixture Magento/Catalog/_files/product_simple_with_custom_store_scope_attribute.php
* @throws NoSuchEntityException
* @throws CouldNotSaveException
* @throws InputException
* @throws StateException
*/
public function testGetAttributeRawValueGetDefault()
{
$product = $this->productRepository->get('simple_with_store_scoped_custom_attribute', true, 0, true);
$product->setCustomAttribute('store_scoped_attribute_code', 'default_value');
$this->productRepository->save($product);

$actual = $this->model->getAttributeRawValue($product->getId(), 'store_scoped_attribute_code', 1);
$this->assertEquals('default_value', $actual);
}

/**
* @magentoAppArea adminhtml
* @magentoDataFixture Magento/Catalog/_files/product_simple_with_custom_store_scope_attribute.php
* @throws NoSuchEntityException
* @throws CouldNotSaveException
* @throws InputException
* @throws StateException
*/
public function testGetAttributeRawValueGetStoreSpecificValueNoDefault()
{
$product = $this->productRepository->get('simple_with_store_scoped_custom_attribute', true, 0, true);
$product->setCustomAttribute('store_scoped_attribute_code', null);
$this->productRepository->save($product);

$product = $this->productRepository->get('simple_with_store_scoped_custom_attribute', true, 1, true);
$product->setCustomAttribute('store_scoped_attribute_code', 'store_value');
$this->productRepository->save($product);

$actual = $this->model->getAttributeRawValue($product->getId(), 'store_scoped_attribute_code', 1);
$this->assertEquals('store_value', $actual);
}

/**
* @magentoAppArea adminhtml
* @magentoDataFixture Magento/Catalog/_files/product_simple_with_custom_store_scope_attribute.php
* @throws NoSuchEntityException
* @throws CouldNotSaveException
* @throws InputException
* @throws StateException
*/
public function testGetAttributeRawValueGetStoreSpecificValueWithDefault()
{
$product = $this->productRepository->get('simple_with_store_scoped_custom_attribute', true, 0, true);
$product->setCustomAttribute('store_scoped_attribute_code', 'default_value');
$this->productRepository->save($product);

$product = $this->productRepository->get('simple_with_store_scoped_custom_attribute', true, 1, true);
$product->setCustomAttribute('store_scoped_attribute_code', 'store_value');
$this->productRepository->save($product);

$actual = $this->model->getAttributeRawValue($product->getId(), 'store_scoped_attribute_code', 1);
$this->assertEquals('store_value', $actual);
}

/**
* @magentoAppArea adminhtml
* @magentoDataFixture Magento/Catalog/_files/product_simple_with_custom_store_scope_attribute.php
* @throws NoSuchEntityException
* @throws CouldNotSaveException
* @throws InputException
* @throws StateException
* @throws NoSuchEntityException
*/
public function testGetAttributeRawValueGetStoreValueFallbackToDefault()
{
$product = $this->productRepository->get('simple_with_store_scoped_custom_attribute', true, 0, true);
$product->setCustomAttribute('store_scoped_attribute_code', 'default_value');
$this->productRepository->save($product);

$actual = $this->model->getAttributeRawValue($product->getId(), 'store_scoped_attribute_code', 1);
$this->assertEquals('default_value', $actual);
}

/**
* @magentoAppArea adminhtml
* @magentoDataFixture Magento/Catalog/_files/product_special_price.php
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

use Magento\TestFramework\Helper\Bootstrap;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\ProductFactory;
use Magento\Catalog\Api\Data\ProductAttributeInterface;
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
use Magento\Catalog\Setup\CategorySetup;
use Magento\Eav\Model\Entity;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Type;

/** @var \Magento\TestFramework\ObjectManager $objectManager */
$objectManager = Bootstrap::getObjectManager();
/** @var ProductRepositoryInterface $productRepository */
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
/** @var ProductFactory $productFactory */
$productFactory = $objectManager->get(ProductFactory::class);
/** @var ProductAttributeRepositoryInterface $attributeRepository */
$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class);


/** @var $installer CategorySetup */
$installer = $objectManager->create(CategorySetup::class);
$entityModel = $objectManager->create(Entity::class);
$attributeSetId = $installer->getAttributeSetId(Product::ENTITY, 'Default');
$entityTypeId = $entityModel->setType(Product::ENTITY)
->getTypeId();
$groupId = $installer->getDefaultAttributeGroupId($entityTypeId, $attributeSetId);

/** @var ProductAttributeInterface $attribute */
$attribute = $objectManager->create(ProductAttributeInterface::class);

$attribute->setAttributeCode('store_scoped_attribute_code')
->setEntityTypeId($entityTypeId)
->setIsVisible(true)
->setFrontendInput('text')
->setIsFilterable(1)
->setIsUserDefined(1)
->setUsedInProductListing(1)
->setBackendType('varchar')
->setIsUsedInGrid(1)
->setIsVisibleInGrid(1)
->setIsFilterableInGrid(1)
->setFrontendLabel('nobody cares')
->setAttributeGroupId($groupId)
->setAttributeSetId(4);

$attributeRepository->save($attribute);

$product = $productFactory->create()
->setTypeId(Type::TYPE_SIMPLE)
->setAttributeSetId(4)
->setName('Simple With Store Scoped Custom Attribute')
->setSku('simple_with_store_scoped_custom_attribute')
->setPrice(100)
->setVisibility(1)
->setStockData(
[
'use_config_manage_stock' => 1,
'qty' => 100,
'is_in_stock' => 1,
]
)
->setStatus(1);
$product->setCustomAttribute('store_scoped_attribute_code', 'default_value');
$productRepository->save($product);
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

use Magento\Framework\Registry;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;

/** @var Magento\Framework\ObjectManagerInterface $objectManager */
$objectManager = Bootstrap::getObjectManager();
/** @var ProductRepositoryInterface $productRepository */
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
/** @var ProductAttributeRepositoryInterface $attributeRepository */
$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class);
/** @var Registry $registry */
$registry = $objectManager->get(Registry::class);

$registry->unregister('isSecureArea');
$registry->register('isSecureArea', true);

try {
/** @var \Magento\Catalog\Api\Data\ProductInterface $product */
$product = $productRepository->get('simple_with_store_scoped_custom_attribute');
$productRepository->delete($product);
} catch (NoSuchEntityException $e) {
}

try {
/** @var \Magento\Catalog\Api\Data\ProductAttributeInterface $attribute */
$attribute = $attributeRepository->get('store_scoped_attribute_code');
$attributeRepository->delete($attribute);
} catch (NoSuchEntityException $e) {
}

$registry->unregister('isSecureArea');
$registry->register('isSecureArea', false);

0 comments on commit 6093314

Please sign in to comment.