Skip to content

Commit

Permalink
Merge pull request #502 from magento-performance/MAGETWO-59138
Browse files Browse the repository at this point in the history
[PERFORMANCE] Bugfixes 2.1
- MAGETWO-59138 Eliminate Slow Query for Media Gallery data
- MAGETWO-59397 [Cloud] Custom theme does not use parent xml configuration on multi thread deployment
- MAGETWO-59309 Static Assets deployment throws errors when redis is used for cache
  • Loading branch information
slavvka authored Oct 17, 2016
2 parents 749bc9c + 32c5539 commit 391e33e
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2211,12 +2211,17 @@ public function addMediaGalleryData()

$mediaGalleries = [];
$linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
$items = $this->getItems();

$select->where('entity.' . $linkField . ' IN (?)', array_map(function ($item) {
return $item->getId();
}, $items));

foreach ($this->getConnection()->fetchAll($select) as $row) {
$mediaGalleries[$row[$linkField]][] = $row;
}

foreach ($this->getItems() as $item) {
foreach ($items as $item) {
$mediaEntries = isset($mediaGalleries[$item->getId()]) ? $mediaGalleries[$item->getId()] : [];
$this->getGalleryReadHandler()->addMediaDataToProduct($item, $mediaEntries);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,26 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
*/
protected $collection;

/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $galleryResourceMock;

/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $entityMock;

/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $metadataPoolMock;

/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $galleryReadHandlerMock;

/**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
Expand Down Expand Up @@ -98,25 +118,49 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();

$entityMock = $this->getMockBuilder('Magento\Eav\Model\Entity\AbstractEntity')
$this->entityMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\AbstractEntity::class)
->disableOriginalConstructor()
->getMock();

$this->galleryResourceMock = $this->getMockBuilder(
\Magento\Catalog\Model\ResourceModel\Product\Gallery::class
)->disableOriginalConstructor()->getMock();

$this->metadataPoolMock = $this->getMockBuilder(
\Magento\Framework\EntityManager\MetadataPool::class
)->disableOriginalConstructor()->getMock();

$this->galleryReadHandlerMock = $this->getMockBuilder(
\Magento\Catalog\Model\Product\Gallery\ReadHandler::class
)->disableOriginalConstructor()->getMock();

$storeManager->expects($this->any())->method('getId')->willReturn(1);
$storeManager->expects($this->any())->method('getStore')->willReturnSelf();
$universalFactory->expects($this->exactly(1))->method('create')->willReturnOnConsecutiveCalls(
$entityMock
$this->entityMock
);
$entityMock->expects($this->once())->method('getConnection')->willReturn($this->connectionMock);
$entityMock->expects($this->once())->method('getDefaultAttributes')->willReturn([]);
$entityMock->expects($this->any())->method('getTable')->willReturnArgument(0);
$this->entityMock->expects($this->once())->method('getConnection')->willReturn($this->connectionMock);
$this->entityMock->expects($this->once())->method('getDefaultAttributes')->willReturn([]);
$this->entityMock->expects($this->any())->method('getTable')->willReturnArgument(0);
$this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock);
$helper = new ObjectManager($this);

$this->prepareObjectManager([
[
'Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation',
$this->getMock('Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation')
],
[
\Magento\Catalog\Model\ResourceModel\Product\Gallery::class,
$this->galleryResourceMock
],
[
\Magento\Framework\EntityManager\MetadataPool::class,
$this->metadataPoolMock
],
[
\Magento\Catalog\Model\Product\Gallery\ReadHandler::class,
$this->galleryReadHandlerMock
]
]);
$this->collection = $helper->getObject(
Expand Down Expand Up @@ -173,6 +217,47 @@ public function testAddProductCategoriesFilter()
$this->collection->addCategoriesFilter([$conditionType => $values]);
}

public function testAddMediaGalleryData()
{
$attributeId = 42;
$itemId = 4242;
$linkField = 'entity_id';
$mediaGalleriesMock = [[$linkField => $itemId]];
$itemMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
->disableOriginalConstructor()
->getMock();
$attributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class)
->disableOriginalConstructor()
->getMock();
$selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
->disableOriginalConstructor()
->getMock();
$metadataMock = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadataInterface::class)
->disableOriginalConstructor()
->getMock();
$this->collection->addItem($itemMock);
$reflection = new \ReflectionClass(get_class($this->collection));
$reflectionProperty = $reflection->getProperty('_isCollectionLoaded');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->collection, true);

$this->galleryResourceMock->expects($this->once())->method('createBatchBaseSelect')->willReturn($selectMock);
$attributeMock->expects($this->once())->method('getAttributeId')->willReturn($attributeId);
$this->entityMock->expects($this->once())->method('getAttribute')->willReturn($attributeMock);
$itemMock->expects($this->atLeastOnce())->method('getId')->willReturn($itemId);
$selectMock->expects($this->once())->method('where')->with('entity.' . $linkField . ' IN (?)', [$itemId]);
$this->metadataPoolMock->expects($this->once())->method('getMetadata')->willReturn($metadataMock);
$metadataMock->expects($this->once())->method('getLinkField')->willReturn($linkField);

$this->connectionMock->expects($this->once())->method('fetchAll')->with($selectMock)->willReturn(
[['entity_id' => $itemId]]
);
$this->galleryReadHandlerMock->expects($this->once())->method('addMediaDataToProduct')
->with($itemMock, $mediaGalleriesMock);

$this->assertSame($this->collection, $this->collection->addMediaGalleryData());
}

/**
* @param $map
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Magento\Framework\Validator\Locale;
use Magento\Deploy\Console\Command\DeployStaticOptionsInterface as Options;
use Magento\Deploy\Model\DeployManager;
use Magento\Framework\App\Cache;
use Magento\Framework\App\Cache\Type\Dummy as DummyCache;

/**
* Deploy static content command
Expand Down Expand Up @@ -380,6 +382,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}

$this->mockCache();
return $deployManager->deploy();
}

Expand Down Expand Up @@ -441,4 +444,18 @@ private function prepareDeployableEntities($filesUtil)

return [$deployableLanguages, $deployableAreaThemeMap, $requestedThemes];
}

/**
* Mock Cache class with dummy implementation
*
* @return void
*/
private function mockCache()
{
$this->objectManager->configure([
'preferences' => [
Cache::class => DummyCache::class
]
]);
}
}
67 changes: 67 additions & 0 deletions lib/internal/Magento/Framework/App/Cache/Type/Dummy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Framework\App\Cache\Type;

use Magento\Framework\App\CacheInterface;

/**
* Dummy cache adapter
*
* for cases when need to disable interaction with cache
* but no specific cache type is used
*/
class Dummy implements CacheInterface
{
/**
* Required by CacheInterface
*
* @return null
*/
public function getFrontend()
{
return null;
}

/**
* Pretend to load data from cache by id
*
* {@inheritdoc}
*/
public function load($identifier)
{
return null;
}

/**
* Pretend to save data
*
* {@inheritdoc}
*/
public function save($data, $identifier, $tags = [], $lifeTime = null)
{
return false;
}

/**
* Pretend to remove cached data by identifier
*
* {@inheritdoc}
*/
public function remove($identifier)
{
return true;
}

/**
* Pretend to clean cached data by specific tag
*
* {@inheritdoc}
*/
public function clean($tags = [])
{
return true;
}
}
2 changes: 1 addition & 1 deletion lib/internal/Magento/Framework/View/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function getViewConfig(array $params = [])
if (isset($params['themeModel'])) {
/** @var \Magento\Framework\View\Design\ThemeInterface $currentTheme */
$currentTheme = $params['themeModel'];
$key = $currentTheme->getCode();
$key = $currentTheme->getFullPath();
if (isset($this->viewConfigs[$key])) {
return $this->viewConfigs[$key];
}
Expand Down
6 changes: 3 additions & 3 deletions lib/internal/Magento/Framework/View/Test/Unit/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@ protected function setUp()

public function testGetViewConfig()
{
$themeCode = 2;
$themeCode = 'area/theme';

$themeMock = $this->getMock(
'Magento\Theme\Model\Theme',
['getCode'],
['getFullPath'],
[],
'',
false
);
$themeMock->expects($this->atLeastOnce())
->method('getCode')
->method('getFullPath')
->will($this->returnValue($themeCode));
$params = [
'themeModel' => $themeMock,
Expand Down

0 comments on commit 391e33e

Please sign in to comment.