Skip to content

Commit

Permalink
Merge branch '2.2-develop' of github.com:magento/magento2 into issue/…
Browse files Browse the repository at this point in the history
…12342/JSTestDriver-removal
  • Loading branch information
omiroshnichenko committed Jan 19, 2018
2 parents ac8aa21 + 83a9b9c commit fa69aa5
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 95 deletions.
172 changes: 85 additions & 87 deletions app/code/Magento/Catalog/Model/Product/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Image as MagentoImage;
use Magento\Framework\Serialize\SerializerInterface;

/**
* @method string getFile()
Expand Down Expand Up @@ -172,6 +173,16 @@ class Image extends \Magento\Framework\Model\AbstractModel
*/
private $imageAsset;

/**
* @var string
*/
private $cachePrefix = 'IMG_INFO';

/**
* @var SerializerInterface
*/
private $serializer;

/**
* Constructor
*
Expand All @@ -190,6 +201,7 @@ class Image extends \Magento\Framework\Model\AbstractModel
* @param array $data
* @param \Magento\Catalog\Model\View\Asset\ImageFactory|null $viewAssetImageFactory
* @param \Magento\Catalog\Model\View\Asset\PlaceholderFactory|null $viewAssetPlaceholderFactory
* @param SerializerInterface|null $serializer
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
Expand All @@ -208,7 +220,8 @@ public function __construct(
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = [],
\Magento\Catalog\Model\View\Asset\ImageFactory $viewAssetImageFactory = null,
\Magento\Catalog\Model\View\Asset\PlaceholderFactory $viewAssetPlaceholderFactory = null
\Magento\Catalog\Model\View\Asset\PlaceholderFactory $viewAssetPlaceholderFactory = null,
SerializerInterface $serializer = null
) {
$this->_storeManager = $storeManager;
$this->_catalogProductMediaConfig = $catalogProductMediaConfig;
Expand All @@ -223,6 +236,7 @@ public function __construct(
->get(\Magento\Catalog\Model\View\Asset\ImageFactory::class);
$this->viewAssetPlaceholderFactory = $viewAssetPlaceholderFactory ?: ObjectManager::getInstance()
->get(\Magento\Catalog\Model\View\Asset\PlaceholderFactory::class);
$this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class);
}

/**
Expand Down Expand Up @@ -356,86 +370,6 @@ public function setSize($size)
return $this;
}

/**
* @param string|null $file
* @return bool
*/
protected function _checkMemory($file = null)
{
return $this->_getMemoryLimit() > $this->_getMemoryUsage() + $this->_getNeedMemoryForFile(
$file
)
|| $this->_getMemoryLimit() == -1;
}

/**
* @return string
*/
protected function _getMemoryLimit()
{
$memoryLimit = trim(strtoupper(ini_get('memory_limit')));

if (!isset($memoryLimit[0])) {
$memoryLimit = "128M";
}

if (substr($memoryLimit, -1) == 'K') {
return substr($memoryLimit, 0, -1) * 1024;
}
if (substr($memoryLimit, -1) == 'M') {
return substr($memoryLimit, 0, -1) * 1024 * 1024;
}
if (substr($memoryLimit, -1) == 'G') {
return substr($memoryLimit, 0, -1) * 1024 * 1024 * 1024;
}
return $memoryLimit;
}

/**
* @return int
*/
protected function _getMemoryUsage()
{
if (function_exists('memory_get_usage')) {
return memory_get_usage();
}
return 0;
}

/**
* @param string|null $file
* @return float|int
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
protected function _getNeedMemoryForFile($file = null)
{
$file = $file === null ? $this->getBaseFile() : $file;
if (!$file) {
return 0;
}

if (!$this->_mediaDirectory->isExist($file)) {
return 0;
}

$imageInfo = getimagesize($this->_mediaDirectory->getAbsolutePath($file));

if (!isset($imageInfo[0]) || !isset($imageInfo[1])) {
return 0;
}
if (!isset($imageInfo['channels'])) {
// if there is no info about this parameter lets set it for maximum
$imageInfo['channels'] = 4;
}
if (!isset($imageInfo['bits'])) {
// if there is no info about this parameter lets set it for maximum
$imageInfo['bits'] = 8;
}
return round(
($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65
);
}

/**
* Convert array of 3 items (decimal r, g, b) to string of their hex values
*
Expand Down Expand Up @@ -472,9 +406,7 @@ public function setBaseFile($file)
'filePath' => $file,
]
);
if ($file == 'no_selection' || !$this->_fileExists($this->imageAsset->getSourceFile())
|| !$this->_checkMemory($this->imageAsset->getSourceFile())
) {
if ($file == 'no_selection' || !$this->_fileExists($this->imageAsset->getSourceFile())) {
$this->_isBaseFilePlaceholder = true;
$this->imageAsset = $this->viewAssetPlaceholderFactory->create(
[
Expand Down Expand Up @@ -682,11 +614,14 @@ public function getDestinationSubdir()
}

/**
* @return bool|void
* @return bool
*/
public function isCached()
{
return file_exists($this->imageAsset->getPath());
return (
is_array($this->loadImageInfoFromCache($this->imageAsset->getPath())) ||
file_exists($this->imageAsset->getPath())
);
}

/**
Expand Down Expand Up @@ -856,6 +791,7 @@ public function clearCache()
$this->_mediaDirectory->delete($directory);

$this->_coreFileStorageDatabase->deleteFolder($this->_mediaDirectory->getAbsolutePath($directory));
$this->clearImageInfoFromCache();
}

/**
Expand Down Expand Up @@ -890,7 +826,7 @@ public function getResizedImageInfo()
$image = $this->imageAsset->getPath();
}

$imageProperties = getimagesize($image);
$imageProperties = $this->getimagesize($image);

return $imageProperties;
} finally {
Expand Down Expand Up @@ -932,4 +868,66 @@ private function getMiscParams()

return $miscParams;
}

/**
* Get image size
*
* @param string $imagePath
* @return array
*/
private function getImageSize($imagePath)
{
$imageInfo = $this->loadImageInfoFromCache($imagePath);
if (!isset($imageInfo['size'])) {
$imageSize = getimagesize($imagePath);
$this->saveImageInfoToCache(['size' => $imageSize], $imagePath);
return $imageSize;
} else {
return $imageInfo['size'];
}
}

/**
* Save image data to cache
*
* @param array $imageInfo
* @param string $imagePath
* @return void
*/
private function saveImageInfoToCache(array $imageInfo, string $imagePath)
{
$imagePath = $this->cachePrefix . $imagePath;
$this->_cacheManager->save(
$this->serializer->serialize($imageInfo),
$imagePath,
[$this->cachePrefix]
);
}

/**
* Load image data from cache
*
* @param string $imagePath
* @return array|false
*/
private function loadImageInfoFromCache(string $imagePath)
{
$imagePath = $this->cachePrefix . $imagePath;
$cacheData = $this->_cacheManager->load($imagePath);
if (!$cacheData) {
return false;
} else {
return $this->serializer->unserialize($cacheData);
}
}

/**
* Clear image data from cache
*
* @return void
*/
private function clearImageInfoFromCache()
{
$this->_cacheManager->clean([$this->cachePrefix]);
}
}
61 changes: 58 additions & 3 deletions app/code/Magento/Catalog/Test/Unit/Model/Product/ImageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
*/
namespace Magento\Catalog\Test\Unit\Model\Product;

use Magento\Catalog\Model\View\Asset\Image\ContextFactory;
use Magento\Catalog\Model\View\Asset\ImageFactory;
use Magento\Catalog\Model\View\Asset\PlaceholderFactory;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\View\Asset\ContextInterface;

/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
Expand Down Expand Up @@ -73,10 +71,24 @@ class ImageTest extends \PHPUnit\Framework\TestCase
*/
private $viewAssetPlaceholderFactory;

/**
* @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
private $serializer;

/**
* @var \Magento\Framework\App\CacheInterface|\PHPUnit_Framework_MockObject_MockObject
*/
private $cacheManager;

protected function setUp()
{
$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$this->context = $this->createMock(\Magento\Framework\Model\Context::class);
$this->cacheManager = $this->getMockBuilder(\Magento\Framework\App\CacheInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->context->expects($this->any())->method('getCacheManager')->will($this->returnValue($this->cacheManager));

$this->storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManager::class)
->disableOriginalConstructor()
Expand Down Expand Up @@ -112,17 +124,36 @@ protected function setUp()
->disableOriginalConstructor()
->setMethods(['create'])
->getMock();
$this->serializer = $this->getMockBuilder(
\Magento\Framework\Serialize\SerializerInterface::class
)->getMockForAbstractClass();
$this->serializer->expects($this->any())
->method('serialize')
->willReturnCallback(
function ($value) {
return json_encode($value);
}
);
$this->serializer->expects($this->any())
->method('unserialize')
->willReturnCallback(
function ($value) {
return json_decode($value, true);
}
);

$this->image = $objectManager->getObject(
\Magento\Catalog\Model\Product\Image::class,
[
'context' => $this->context,
'storeManager' => $this->storeManager,
'catalogProductMediaConfig' => $this->config,
'coreFileStorageDatabase' => $this->coreFileHelper,
'filesystem' => $this->filesystem,
'imageFactory' => $this->factory,
'viewAssetImageFactory' => $this->viewAssetImageFactory,
'viewAssetPlaceholderFactory' => $this->viewAssetPlaceholderFactory
'viewAssetPlaceholderFactory' => $this->viewAssetPlaceholderFactory,
'serializer' => $this->serializer
]
);

Expand Down Expand Up @@ -354,12 +385,16 @@ public function testIsCached()
$this->testSetGetBaseFile();
$absolutePath = dirname(dirname(__DIR__)) . '/_files/catalog/product/watermark/somefile.png';
$this->imageAsset->expects($this->any())->method('getPath')->willReturn($absolutePath);
$this->cacheManager->expects($this->once())->method('load')->willReturn(
json_encode(['size' => ['image data']])
);
$this->assertTrue($this->image->isCached());
}

public function testClearCache()
{
$this->coreFileHelper->expects($this->once())->method('deleteFolder')->will($this->returnValue(true));
$this->cacheManager->expects($this->once())->method('clean');
$this->image->clearCache();
}

Expand All @@ -383,4 +418,24 @@ public function testIsBaseFilePlaceholder()
{
$this->assertFalse($this->image->isBaseFilePlaceholder());
}

public function testGetResizedImageInfoWithCache()
{
$absolutePath = dirname(dirname(__DIR__)) . '/_files/catalog/product/watermark/somefile.png';
$this->imageAsset->expects($this->any())->method('getPath')->willReturn($absolutePath);
$this->cacheManager->expects($this->once())->method('load')->willReturn(
json_encode(['size' => ['image data']])
);
$this->cacheManager->expects($this->never())->method('save');
$this->assertEquals(['image data'], $this->image->getResizedImageInfo());
}

public function testGetResizedImageInfoEmptyCache()
{
$absolutePath = dirname(dirname(__DIR__)) . '/_files/catalog/product/watermark/somefile.png';
$this->imageAsset->expects($this->any())->method('getPath')->willReturn($absolutePath);
$this->cacheManager->expects($this->once())->method('load')->willReturn(false);
$this->cacheManager->expects($this->once())->method('save');
$this->assertTrue(is_array($this->image->getResizedImageInfo()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@
<listingToolbar name="listing_top">
<bookmark name="bookmarks"/>
<columnsControls name="columns_controls"/>
<exportButton name="export_button"/>
<exportButton name="export_button">
<settings>
<additionalParams>
<param xsi:type="string" active="true" name="order_id">*</param>
</additionalParams>
</settings>
</exportButton>
<filterSearch name="fulltext"/>
<filters name="listing_filters">
<filterSelect name="store_id" provider="${ $.parentName }">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@
<listingToolbar name="listing_top">
<bookmark name="bookmarks"/>
<columnsControls name="columns_controls"/>
<exportButton name="export_button"/>
<exportButton name="export_button">
<settings>
<additionalParams>
<param xsi:type="string" active="true" name="order_id">*</param>
</additionalParams>
</settings>
</exportButton>
<filterSearch name="fulltext"/>
<filters name="listing_filters">
<filterSelect name="store_id" provider="${ $.parentName }">
Expand Down
Loading

0 comments on commit fa69aa5

Please sign in to comment.