Skip to content

Commit

Permalink
Merge remote-tracking branch 'mainline/2.2-develop' into MAGETWO-8051…
Browse files Browse the repository at this point in the history
…4-PR-11155
  • Loading branch information
dmanners committed Oct 6, 2017
2 parents 3102ed7 + 2eaf779 commit c2de09a
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\EntityManager\MetadataPool;

/**
* Abstract action reindex class
Expand Down Expand Up @@ -70,25 +71,33 @@ abstract class AbstractAction
*/
private $cacheCleaner;

/**
* @var MetadataPool
*/
private $metadataPool;

/**
* @param ResourceConnection $resource
* @param \Magento\CatalogInventory\Model\ResourceModel\Indexer\StockFactory $indexerFactory
* @param \Magento\Catalog\Model\Product\Type $catalogProductType
* @param \Magento\Framework\Indexer\CacheContext $cacheContext
* @param \Magento\Framework\Event\ManagerInterface $eventManager
* @param MetadataPool|null $metadataPool
*/
public function __construct(
ResourceConnection $resource,
\Magento\CatalogInventory\Model\ResourceModel\Indexer\StockFactory $indexerFactory,
\Magento\Catalog\Model\Product\Type $catalogProductType,
\Magento\Framework\Indexer\CacheContext $cacheContext,
\Magento\Framework\Event\ManagerInterface $eventManager
\Magento\Framework\Event\ManagerInterface $eventManager,
MetadataPool $metadataPool = null
) {
$this->_resource = $resource;
$this->_indexerFactory = $indexerFactory;
$this->_catalogProductType = $catalogProductType;
$this->cacheContext = $cacheContext;
$this->eventManager = $eventManager;
$this->metadataPool = $metadataPool ?: ObjectManager::getInstance()->get(MetadataPool::class);
}

/**
Expand Down Expand Up @@ -154,10 +163,15 @@ protected function _getTable($entityName)
public function getRelationsByChild($childIds)
{
$connection = $this->_getConnection();
$select = $connection->select()
->from($this->_getTable('catalog_product_relation'), 'parent_id')
->where('child_id IN(?)', $childIds);

$linkField = $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class)
->getLinkField();
$select = $connection->select()->from(
['cpe' => $this->_getTable('catalog_product_entity')],
'entity_id'
)->join(
['relation' => $this->_getTable('catalog_product_relation')],
'relation.parent_id = cpe.' . $linkField
)->where('child_id IN(?)', $childIds);
return $connection->fetchCol($select);
}

Expand Down Expand Up @@ -230,7 +244,8 @@ protected function _reindexRows($productIds = [])
if (!is_array($productIds)) {
$productIds = [$productIds];
}

$parentIds = $this->getRelationsByChild($productIds);
$productIds = $parentIds ? array_unique(array_merge($parentIds, $productIds)) : $productIds;
$this->getCacheCleaner()->clean($productIds, function () use ($productIds) {
$this->doReindex($productIds);
});
Expand All @@ -248,13 +263,10 @@ private function doReindex($productIds = [])
{
$connection = $this->_getConnection();

$parentIds = $this->getRelationsByChild($productIds);
$processIds = $parentIds ? array_merge($parentIds, $productIds) : $productIds;

// retrieve product types by processIds
$select = $connection->select()
->from($this->_getTable('catalog_product_entity'), ['entity_id', 'type_id'])
->where('entity_id IN(?)', $processIds);
->where('entity_id IN(?)', $productIds);
$pairs = $connection->fetchPairs($select);

$byType = [];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\CatalogInventory\Model\Plugin;

use Magento\Catalog\Model\Product\Action as ProductAction;

/**
* Plugin for Magento\Catalog\Model\Product\Action
*/
class ReindexUpdatedProducts
{
/**
* @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor
*/
private $indexerProcessor;

/**
* @param \Magento\CatalogInventory\Model\Indexer\Stock\Processor $indexerProcessor
*/
public function __construct(\Magento\CatalogInventory\Model\Indexer\Stock\Processor $indexerProcessor)
{
$this->indexerProcessor = $indexerProcessor;
}

/**
* Reindex on product attribute mass change
*
* @param ProductAction $subject
* @param ProductAction $action
* @param array $productIds
* @return ProductAction
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterUpdateAttributes(
ProductAction $subject,
ProductAction $action,
$productIds
) {
$this->indexerProcessor->reindexList(array_unique($productIds));
return $action;
}
}
3 changes: 3 additions & 0 deletions app/code/Magento/CatalogInventory/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@
<type name="Magento\Catalog\Model\Product">
<plugin name="catalogInventoryAfterLoad" type="Magento\CatalogInventory\Model\Plugin\AfterProductLoad"/>
</type>
<type name="Magento\Catalog\Model\Product\Action">
<plugin name="ReindexUpdatedProducts" type="Magento\CatalogInventory\Model\Plugin\ReindexUpdatedProducts"/>
</type>
<type name="Magento\CatalogInventory\Setup\UpgradeData">
<arguments>
<argument name="indexerProcessor" xsi:type="object">Magento\CatalogInventory\Model\Indexer\Stock\Processor</argument>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,73 @@ public function testUpdateWebsites()
}
}

/**
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
* @magentoAppArea adminhtml
* @param string $status
* @param string $productsCount
* @dataProvider updateAttributesDataProvider
*/
public function testUpdateAttributes($status, $productsCount)
{
/** @var \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry */
$indexerRegistry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
->get(\Magento\Framework\Indexer\IndexerRegistry::class);
$indexerRegistry->get(Fulltext::INDEXER_ID)->setScheduled(false);

/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
$productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);

/** @var \Magento\Catalog\Model\Product $product */
$product = $productRepository->get('configurable');
$productAttributesOptions = $product->getExtensionAttributes()->getConfigurableProductLinks();
$attrData = ['status' => $status];
$configurableOptionsId = [];
if (isset($productAttributesOptions)) {
foreach ($productAttributesOptions as $configurableOption) {
$configurableOptionsId[] = $configurableOption;
}
}
$this->action->updateAttributes($configurableOptionsId, $attrData, $product->getStoreId());

$categoryFactory = $this->objectManager->create(\Magento\Catalog\Model\CategoryFactory::class);
/** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */
$listProduct = $this->objectManager->create(\Magento\Catalog\Block\Product\ListProduct::class);
$category = $categoryFactory->create()->load(2);
$layer = $listProduct->getLayer();
$layer->setCurrentCategory($category);
$productCollection = $layer->getProductCollection();
$productCollection->joinField(
'qty',
'cataloginventory_stock_status',
'qty',
'product_id=entity_id',
'{{table}}.stock_id=1',
'left'
);

$this->assertEquals($productsCount, $productCollection->count());
}

/**
* DataProvider for testUpdateAttributes
*
* @return array
*/
public function updateAttributesDataProvider()
{
return [
[
'status' => 2,
'expected_count' => 0
],
[
'status' => 1,
'expected_count' => 1
],
];
}

public static function tearDownAfterClass()
{
/** @var \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Catalog\Model\Product\Type;
use Magento\Catalog\Model\Product\Visibility;
use Magento\GroupedProduct\Model\Product\Type\Grouped;
use Magento\TestFramework\Helper\Bootstrap;

/** @var ProductRepositoryInterface $productRepository */
$productRepository = Bootstrap::getObjectManager()
->get(ProductRepositoryInterface::class);

$productLinkFactory = Bootstrap::getObjectManager()
->get(\Magento\Catalog\Api\Data\ProductLinkInterfaceFactory::class);
$productIds = ['11', '22'];

foreach ($productIds as $productId) {
/** @var $product Product */
$product = Bootstrap::getObjectManager()->create(Product::class);
$product->setTypeId(Type::TYPE_SIMPLE)
->setId($productId)
->setWebsiteIds([1])
->setAttributeSetId(4)
->setName('Simple ' . $productId)
->setSku('simple_' . $productId)
->setPrice(100)
->setVisibility(Visibility::VISIBILITY_BOTH)
->setStatus(Status::STATUS_ENABLED)
->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]);

$linkedProducts[] = $productRepository->save($product);
}

/** @var $product Product */
$product = Bootstrap::getObjectManager()->create(Product::class);

$product->setTypeId(Grouped::TYPE_CODE)
->setId(1)
->setWebsiteIds([1])
->setAttributeSetId(4)
->setName('Grouped Product')
->setSku('grouped')
->setVisibility(Visibility::VISIBILITY_BOTH)
->setStatus(Status::STATUS_ENABLED)
->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]);

foreach ($linkedProducts as $linkedProduct) {
/** @var \Magento\Catalog\Api\Data\ProductLinkInterface $productLink */
$productLink = $productLinkFactory->create();
$productLink->setSku($product->getSku())
->setLinkType('associated')
->setLinkedProductSku($linkedProduct->getSku())
->setLinkedProductType($linkedProduct->getTypeId())
->getExtensionAttributes()
->setQty(1);
$newLinks[] = $productLink;
}

$product->setProductLinks($newLinks);

$productRepository->save($product);
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();

/** @var \Magento\Framework\Registry $registry */
$registry = $objectManager->get(\Magento\Framework\Registry::class);

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

/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
->get(\Magento\Catalog\Api\ProductRepositoryInterface::class);

$skuList = ['simple_11', 'simple_22', 'grouped'];
foreach ($skuList as $sku) {
try {
$product = $productRepository->get($sku, false, null, true);

$stockStatus = $objectManager->create(\Magento\CatalogInventory\Model\Stock\Status::class);
$stockStatus->load($product->getEntityId(), 'product_id');
$stockStatus->delete();

$productRepository->delete($product);
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
//Product already removed
}
}

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

0 comments on commit c2de09a

Please sign in to comment.