diff --git a/app/code/Magento/Backend/Block/Store/Switcher.php b/app/code/Magento/Backend/Block/Store/Switcher.php
index 21c066fbef056..1dccfa05b1757 100644
--- a/app/code/Magento/Backend/Block/Store/Switcher.php
+++ b/app/code/Magento/Backend/Block/Store/Switcher.php
@@ -155,11 +155,7 @@ public function getWebsites()
{
$websites = $this->_storeManager->getWebsites();
if ($websiteIds = $this->getWebsiteIds()) {
- foreach (array_keys($websites) as $websiteId) {
- if (!in_array($websiteId, $websiteIds)) {
- unset($websites[$websiteId]);
- }
- }
+ $websites = array_intersect_key($websites, array_flip($websiteIds));
}
return $websites;
}
diff --git a/app/code/Magento/Backend/Model/Auth/Session.php b/app/code/Magento/Backend/Model/Auth/Session.php
index 7dddeba08a304..fc8ddffb3a916 100644
--- a/app/code/Magento/Backend/Model/Auth/Session.php
+++ b/app/code/Magento/Backend/Model/Auth/Session.php
@@ -177,14 +177,10 @@ public function isLoggedIn()
*/
public function prolong()
{
- $lifetime = $this->_config->getValue(self::XML_PATH_SESSION_LIFETIME);
- $currentTime = time();
-
- $this->setUpdatedAt($currentTime);
$cookieValue = $this->cookieManager->getCookie($this->getName());
if ($cookieValue) {
+ $this->setUpdatedAt(time());
$cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata()
- ->setDuration($lifetime)
->setPath($this->sessionConfig->getCookiePath())
->setDomain($this->sessionConfig->getCookieDomain())
->setSecure($this->sessionConfig->getCookieSecure())
diff --git a/app/code/Magento/Backend/Test/Unit/Block/Store/SwitcherTest.php b/app/code/Magento/Backend/Test/Unit/Block/Store/SwitcherTest.php
new file mode 100644
index 0000000000000..a4ba16ea1bdaa
--- /dev/null
+++ b/app/code/Magento/Backend/Test/Unit/Block/Store/SwitcherTest.php
@@ -0,0 +1,53 @@
+storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class);
+ $objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+ $context = $objectHelper->getObject(
+ \Magento\Backend\Block\Template\Context::class,
+ [
+ 'storeManager' => $this->storeManagerMock,
+ ]
+ );
+
+ $this->switcherBlock = $objectHelper->getObject(
+ \Magento\Backend\Block\Store\Switcher::class,
+ ['context' => $context]
+ );
+ }
+
+ public function testGetWebsites()
+ {
+ $websiteMock = $this->getMock(\Magento\Store\Model\Website::class, [], [], '', false);
+ $websites = [0 => $websiteMock, 1 => $websiteMock];
+ $this->storeManagerMock->expects($this->once())->method('getWebsites')->will($this->returnValue($websites));
+ $this->assertEquals($websites, $this->switcherBlock->getWebsites());
+ }
+
+ public function testGetWebsitesIfSetWebsiteIds()
+ {
+ $websiteMock = $this->getMock(\Magento\Store\Model\Website::class, [], [], '', false);
+ $websites = [0 => $websiteMock, 1 => $websiteMock];
+ $this->storeManagerMock->expects($this->once())->method('getWebsites')->will($this->returnValue($websites));
+
+ $this->switcherBlock->setWebsiteIds([1]);
+ $expected = [1 => $websiteMock];
+ $this->assertEquals($expected, $this->switcherBlock->getWebsites());
+ }
+}
diff --git a/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php b/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php
index b05e8b31f390c..e12e8b55f38b0 100644
--- a/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php
+++ b/app/code/Magento/Backend/Test/Unit/Model/Auth/SessionTest.php
@@ -164,17 +164,11 @@ public function testProlong()
{
$name = session_name();
$cookie = 'cookie';
- $lifetime = 900;
$path = '/';
$domain = 'magento2';
$secure = true;
$httpOnly = true;
-
$cookieMetadata = $this->getMock('Magento\Framework\Stdlib\Cookie\PublicCookieMetadata');
- $cookieMetadata->expects($this->once())
- ->method('setDuration')
- ->with($lifetime)
- ->will($this->returnSelf());
$cookieMetadata->expects($this->once())
->method('setPath')
->with($path)
@@ -191,11 +185,9 @@ public function testProlong()
->method('setHttpOnly')
->with($httpOnly)
->will($this->returnSelf());
-
$this->cookieMetadataFactory->expects($this->once())
->method('createPublicCookieMetadata')
->will($this->returnValue($cookieMetadata));
-
$this->cookieManager->expects($this->once())
->method('getCookie')
->with($name)
@@ -203,11 +195,6 @@ public function testProlong()
$this->cookieManager->expects($this->once())
->method('setPublicCookie')
->with($name, $cookie, $cookieMetadata);
-
- $this->config->expects($this->once())
- ->method('getValue')
- ->with(\Magento\Backend\Model\Auth\Session::XML_PATH_SESSION_LIFETIME)
- ->will($this->returnValue($lifetime));
$this->sessionConfig->expects($this->once())
->method('getCookiePath')
->will($this->returnValue($path));
@@ -220,9 +207,7 @@ public function testProlong()
$this->sessionConfig->expects($this->once())
->method('getCookieHttpOnly')
->will($this->returnValue($httpOnly));
-
$this->session->prolong();
-
$this->assertLessThanOrEqual(time(), $this->session->getUpdatedAt());
}
diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php
index 5d8d7c2bba8a1..9a289fdc0c9cc 100644
--- a/app/code/Magento/Bundle/Model/Product/Type.php
+++ b/app/code/Magento/Bundle/Model/Product/Type.php
@@ -716,6 +716,12 @@ protected function _prepareProduct(\Magento\Framework\DataObject $buyRequest, $p
if (!empty($selectionIds)) {
$selections = $this->getSelectionsByIds($selectionIds, $product);
+ if (count($selections->getItems()) !== count($selectionIds)) {
+ throw new \Magento\Framework\Exception\LocalizedException(
+ __('The options you selected are not available.')
+ );
+ }
+
// Check if added selections are still on sale
$this->checkSelectionsIsSale(
$selections,
@@ -888,12 +894,6 @@ public function getSelectionsByIds($selectionIds, $product)
->addFilterByRequiredOptions()
->setSelectionIdsFilter($selectionIds);
- if (count($usedSelections->getItems()) !== count($selectionIds)) {
- throw new \Magento\Framework\Exception\LocalizedException(
- __('The options you selected are not available.')
- );
- }
-
if (!$this->_catalogData->isPriceGlobal() && $storeId) {
$websiteId = $this->_storeManager->getStore($storeId)
->getWebsiteId();
diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php
index 106c9879fbb7b..c60c0f33d189c 100644
--- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php
+++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php
@@ -377,7 +377,7 @@ function ($key) use ($optionCollection, $selectionCollection) {
$resultValue = $selectionCollection;
break;
case '_cache_instance_used_selections_ids':
- $resultValue = [2, 5, 14];
+ $resultValue = [5];
break;
}
@@ -402,7 +402,7 @@ function ($key) use ($optionCollection, $selectionCollection) {
->method('setStoreFilter');
$buyRequest->expects($this->once())
->method('getBundleOption')
- ->willReturn([3 => 5, 10 => [7 => 2, 11 => 14]]);
+ ->willReturn([3 => 5]);
$selectionCollection->expects($this->any())
->method('getItems')
->willReturn([$selection]);
@@ -431,13 +431,13 @@ function ($key) use ($optionCollection, $selectionCollection) {
->willReturn($productType);
$option->expects($this->at(3))
->method('getId')
- ->willReturn(10);
+ ->willReturn(3);
$option->expects($this->at(9))
->method('getId')
- ->willReturn(10);
+ ->willReturn(3);
$option->expects($this->once())
->method('getRequired')
- ->willReturn(true);
+ ->willReturn(false);
$option->expects($this->once())
->method('isMultiSelection')
->willReturn(true);
@@ -608,7 +608,7 @@ function ($key) use ($optionCollection, $selectionCollection) {
$resultValue = $selectionCollection;
break;
case '_cache_instance_used_selections_ids':
- $resultValue = [2, 5, 14];
+ $resultValue = [5];
break;
}
@@ -633,7 +633,7 @@ function ($key) use ($optionCollection, $selectionCollection) {
->method('setStoreFilter');
$buyRequest->expects($this->once())
->method('getBundleOption')
- ->willReturn([3 => 5, 10 => [7 => 2, 11 => 14]]);
+ ->willReturn([3 => 5]);
$selectionCollection->expects($this->any())
->method('getItems')
->willReturn([$selection]);
@@ -662,13 +662,13 @@ function ($key) use ($optionCollection, $selectionCollection) {
->willReturn($productType);
$option->expects($this->at(3))
->method('getId')
- ->willReturn(10);
+ ->willReturn(3);
$option->expects($this->at(9))
->method('getId')
- ->willReturn(10);
+ ->willReturn(3);
$option->expects($this->once())
->method('getRequired')
- ->willReturn(true);
+ ->willReturn(false);
$option->expects($this->once())
->method('isMultiSelection')
->willReturn(true);
@@ -827,7 +827,7 @@ function ($key) use ($optionCollection, $selectionCollection) {
$resultValue = $selectionCollection;
break;
case '_cache_instance_used_selections_ids':
- $resultValue = [2, 5, 14];
+ $resultValue = [5];
break;
}
@@ -852,7 +852,7 @@ function ($key) use ($optionCollection, $selectionCollection) {
->method('setStoreFilter');
$buyRequest->expects($this->once())
->method('getBundleOption')
- ->willReturn([3 => 5, 10 => [7 => 2, 11 => 14]]);
+ ->willReturn([3 => 5]);
$selectionCollection->expects($this->any())
->method('getItems')
->willReturn([$selection]);
@@ -881,13 +881,13 @@ function ($key) use ($optionCollection, $selectionCollection) {
->willReturn($productType);
$option->expects($this->at(3))
->method('getId')
- ->willReturn(10);
+ ->willReturn(3);
$option->expects($this->at(9))
->method('getId')
- ->willReturn(10);
+ ->willReturn(3);
$option->expects($this->once())
->method('getRequired')
- ->willReturn(true);
+ ->willReturn(false);
$option->expects($this->once())
->method('isMultiSelection')
->willReturn(true);
@@ -1112,41 +1112,29 @@ function ($key) use ($optionCollection, $selectionCollection) {
$resultValue = $selectionCollection;
break;
case '_cache_instance_used_selections_ids':
- $resultValue = [2, 5, 14];
+ $resultValue = [5];
break;
}
return $resultValue;
}
);
- $optionCollection->expects($this->once())
- ->method('getItemById')
- ->willReturn($option);
$optionCollection->expects($this->once())
->method('appendSelections');
$productType->expects($this->once())
->method('setStoreFilter');
$buyRequest->expects($this->once())
->method('getBundleOption')
- ->willReturn([3 => 5, 10 => [7 => 2, 11 => 14]]);
+ ->willReturn([3 => 5]);
$selectionCollection->expects($this->at(0))
->method('getItems')
->willReturn([$selection]);
$selectionCollection->expects($this->at(1))
->method('getItems')
->willReturn([]);
- $selection->expects($this->once())
- ->method('isSalable')
- ->willReturn(false);
- $option->expects($this->at(3))
+ $option->expects($this->any())
->method('getId')
- ->willReturn(10);
- $option->expects($this->once())
- ->method('getRequired')
- ->willReturn(true);
- $option->expects($this->once())
- ->method('isMultiSelection')
- ->willReturn(true);
+ ->willReturn(3);
$result = $this->model->prepareForCartAdvanced($buyRequest, $product);
$this->assertEquals('Please specify product option(s).', $result);
@@ -1255,7 +1243,7 @@ function ($key) use ($optionCollection, $selectionCollection) {
$buyRequest->expects($this->once())
->method('getBundleOption')
->willReturn([3 => 5]);
- $selectionCollection->expects($this->once())
+ $selectionCollection->expects($this->any())
->method('getItems')
->willReturn([$selection]);
$selection->expects($this->once())
@@ -1901,8 +1889,7 @@ public function testGetSelectionsByIds()
'setPositionOrder',
'addFilterByRequiredOptions',
'setSelectionIdsFilter',
- 'joinPrices',
- 'getItems'
+ 'joinPrices'
]
)
->disableOriginalConstructor()
@@ -1971,9 +1958,6 @@ public function testGetSelectionsByIds()
->method('setSelectionIdsFilter')
->with($selectionIds)
->will($this->returnSelf());
- $usedSelectionsMock->expects($this->once())
- ->method('getItems')
- ->willReturn($usedSelectionsIds);
$usedSelectionsMock->expects($this->once())
->method('joinPrices')
@@ -1987,96 +1971,6 @@ public function testGetSelectionsByIds()
$this->model->getSelectionsByIds($selectionIds, $productMock);
}
- /**
- * @expectedException \Magento\Framework\Exception\LocalizedException
- * @expectedExceptionMessage The options you selected are not available.
- *
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
- */
- public function testGetSelectionsByIdsException()
- {
- $selectionIds = [1, 2, 3];
- $usedSelectionsIds = [4, 5];
- $storeId = 2;
- $storeFilter = 'store_filter';
- $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product')
- ->disableOriginalConstructor()
- ->getMock();
- $usedSelectionsMock = $this->getMockBuilder('Magento\Bundle\Model\ResourceModel\Selection\Collection')
- ->setMethods(
- [
- 'addAttributeToSelect',
- 'setFlag',
- 'addStoreFilter',
- 'setStoreId',
- 'setPositionOrder',
- 'addFilterByRequiredOptions',
- 'setSelectionIdsFilter',
- 'joinPrices',
- 'getItems'
- ]
- )
- ->disableOriginalConstructor()
- ->getMock();
- $productGetMap = [
- ['_cache_instance_used_selections', null, null],
- ['_cache_instance_used_selections_ids', null, $usedSelectionsIds],
- ['_cache_instance_store_filter', null, $storeFilter],
- ];
- $productMock->expects($this->any())
- ->method('getData')
- ->will($this->returnValueMap($productGetMap));
- $productSetMap = [
- ['_cache_instance_used_selections', $usedSelectionsMock, $productMock],
- ['_cache_instance_used_selections_ids', $selectionIds, $productMock],
- ];
- $productMock->expects($this->any())
- ->method('setData')
- ->will($this->returnValueMap($productSetMap));
- $productMock->expects($this->once())
- ->method('getStoreId')
- ->will($this->returnValue($storeId));
-
- $this->bundleCollection->expects($this->once())
- ->method('create')
- ->will($this->returnValue($usedSelectionsMock));
-
- $usedSelectionsMock->expects($this->once())
- ->method('addAttributeToSelect')
- ->with('*')
- ->will($this->returnSelf());
- $flagMap = [
- ['require_stock_items', true, $usedSelectionsMock],
- ['product_children', true, $usedSelectionsMock],
- ];
- $usedSelectionsMock->expects($this->any())
- ->method('setFlag')
- ->will($this->returnValueMap($flagMap));
- $usedSelectionsMock->expects($this->once())
- ->method('addStoreFilter')
- ->with($storeFilter)
- ->will($this->returnSelf());
- $usedSelectionsMock->expects($this->once())
- ->method('setStoreId')
- ->with($storeId)
- ->will($this->returnSelf());
- $usedSelectionsMock->expects($this->once())
- ->method('setPositionOrder')
- ->will($this->returnSelf());
- $usedSelectionsMock->expects($this->once())
- ->method('addFilterByRequiredOptions')
- ->will($this->returnSelf());
- $usedSelectionsMock->expects($this->once())
- ->method('setSelectionIdsFilter')
- ->with($selectionIds)
- ->will($this->returnSelf());
- $usedSelectionsMock->expects($this->once())
- ->method('getItems')
- ->willReturn($usedSelectionsIds);
-
-
- $this->model->getSelectionsByIds($selectionIds, $productMock);
- }
/**
* @return void
*/
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php
index d7af88edabd5f..944dd302b8c6b 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php
@@ -2171,6 +2171,7 @@ public function addPriceDataFieldFilter($comparisonFormat, $fields)
*/
public function addMediaGalleryData()
{
+
if ($this->getFlag('media_gallery_added')) {
return $this;
}
@@ -2186,7 +2187,11 @@ public function addMediaGalleryData()
$this->getStoreId(),
$attribute->getAttributeId()
);
-
+
+ $select->where('entity.entity_id IN (?)', array_map(function ($item) {
+ return $item->getId();
+ }, $this->getItems()));
+
foreach ($this->getConnection()->fetchAll($select) as $row) {
$mediaGalleries[$row['entity_id']][] = $row;
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php
index 7536dbf1b3a4d..5d80d2bab5443 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php
@@ -28,6 +28,16 @@ class CollectionTest extends \PHPUnit_Framework_TestCase
*/
protected $collection;
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $galleryResourceMock;
+
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $entityMock;
+
/**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
@@ -98,18 +108,22 @@ public 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\Attribute\Backend\Media::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->collection = $helper->getObject(
@@ -138,6 +152,11 @@ public function setUp()
]
);
$this->collection->setConnection($this->connectionMock);
+
+ $reflection = new \ReflectionClass(get_class($this->collection));
+ $reflectionProperty = $reflection->getProperty('mediaGalleryResource');
+ $reflectionProperty->setAccessible(true);
+ $reflectionProperty->setValue($this->collection, $this->galleryResourceMock);
}
public function testAddProductCategoriesFilter()
@@ -165,4 +184,42 @@ public function testAddProductCategoriesFilter()
)->willReturnSelf();
$this->collection->addCategoriesFilter([$conditionType => $values]);
}
+
+ public function testAddMediaGalleryData()
+ {
+ $attributeId = 42;
+ $itemId = 4242;
+ $mediaGalleriesMock = [['entity_id' => $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();
+ $backendMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Attribute\Backend\Media::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.entity_id IN (?)', [$itemId]);
+
+ $this->connectionMock->expects($this->once())->method('fetchAll')->with($selectMock)->willReturn(
+ [['entity_id' => $itemId]]
+ );
+ $attributeMock->expects($this->once())->method('getBackend')->willReturn($backendMock);
+ $backendMock->expects($this->once())->method('addMediaDataToProduct')->with($itemMock, $mediaGalleriesMock);
+
+ $this->assertSame($this->collection, $this->collection->addMediaGalleryData());
+ }
}
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml
index f6dd2a0033fd4..41f0684a43126 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/form.phtml
@@ -40,9 +40,11 @@
diff --git a/app/code/Magento/Swatches/view/frontend/web/js/SwatchRenderer.js b/app/code/Magento/Swatches/view/frontend/web/js/SwatchRenderer.js
index 2549d4d9b62cf..9859a3c74236a 100644
--- a/app/code/Magento/Swatches/view/frontend/web/js/SwatchRenderer.js
+++ b/app/code/Magento/Swatches/view/frontend/web/js/SwatchRenderer.js
@@ -191,6 +191,7 @@ define(['jquery', 'underscore', 'jquery/ui'], function ($, _) {
_init: function () {
if (this.options.jsonConfig != '' && this.options.jsonSwatchConfig != '') {
this._RenderControls();
+ $(this.element).trigger('swatch.initialized');
} else {
console.log('SwatchRenderer: No input data received');
}
@@ -834,6 +835,30 @@ define(['jquery', 'underscore', 'jquery/ui'], function ($, _) {
});
},
+ /**
+ * Emulate mouse click or selection change on all swatches that should be selected
+ * @param {Object} [selectedAttributes]
+ * @private
+ */
+ _EmulateSelectedByAttributeId: function (selectedAttributes) {
+ $.each(selectedAttributes, $.proxy(function (attributeId, optionId) {
+ var elem = this.element.find('.' + this.options.classes.attributeClass +
+ '[attribute-id="' + attributeId + '"] [option-id="' + optionId + '"]'),
+ parentInput = elem.parent();
+
+ if (elem.hasClass('selected')) {
+ return;
+ }
+
+ if (parentInput.hasClass(this.options.classes.selectClass)) {
+ parentInput.val(optionId);
+ parentInput.trigger('change');
+ } else {
+ elem.trigger('click');
+ }
+ }, this));
+ },
+
/**
* Returns an array/object's length
* @param obj
@@ -851,4 +876,5 @@ define(['jquery', 'underscore', 'jquery/ui'], function ($, _) {
return size;
}
});
+ return $.custom.SwatchRenderer;
});
diff --git a/app/code/Magento/Swatches/view/frontend/web/js/configurable-customer-data.js b/app/code/Magento/Swatches/view/frontend/web/js/configurable-customer-data.js
new file mode 100644
index 0000000000000..7ae2477513cf6
--- /dev/null
+++ b/app/code/Magento/Swatches/view/frontend/web/js/configurable-customer-data.js
@@ -0,0 +1,33 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+require([
+ 'jquery',
+ 'Magento_ConfigurableProduct/js/options-updater'
+], function ($, Updater) {
+ 'use strict';
+
+ var selectors = {
+ formSelector: '#product_addtocart_form',
+ swatchSelector: '.swatch-opt'
+ },
+ swatchWidgetName = 'customSwatchRenderer',
+ widgetInitEvent = 'swatch.initialized',
+
+ /**
+ * Sets all configurable swatch attribute's selected values
+ */
+ updateSwatchOptions = function () {
+ var swatchWidget = $(selectors.swatchSelector).data(swatchWidgetName);
+
+ if (!swatchWidget || !swatchWidget._EmulateSelectedByAttributeId) {
+ return;
+ }
+ swatchWidget._EmulateSelectedByAttributeId(this.productOptions);
+ },
+ updater = new Updater(widgetInitEvent, updateSwatchOptions);
+
+ updater.listen();
+});
diff --git a/app/code/Magento/Tax/Api/TaxClassRepositoryInterface.php b/app/code/Magento/Tax/Api/TaxClassRepositoryInterface.php
index bdbd968635880..af08e14325e94 100644
--- a/app/code/Magento/Tax/Api/TaxClassRepositoryInterface.php
+++ b/app/code/Magento/Tax/Api/TaxClassRepositoryInterface.php
@@ -25,6 +25,10 @@ public function get($taxClassId);
/**
* Retrieve tax classes which match a specific criteria.
*
+ * This call returns an array of objects, but detailed information about each object’s attributes might not be
+ * included. See http://devdocs.magento.com/codelinks/attributes.html#TaxClassRepositoryInterface to
+ * determine which call to use to get detailed information about all attributes for an object.
+ *
* @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
* @return \Magento\Tax\Api\Data\TaxClassSearchResultsInterface containing Data\TaxClassInterface
* @throws \Magento\Framework\Exception\InputException
diff --git a/app/code/Magento/Tax/Api/TaxRateRepositoryInterface.php b/app/code/Magento/Tax/Api/TaxRateRepositoryInterface.php
index 88ec624cdbdd3..b4fa0d9ef64fd 100644
--- a/app/code/Magento/Tax/Api/TaxRateRepositoryInterface.php
+++ b/app/code/Magento/Tax/Api/TaxRateRepositoryInterface.php
@@ -45,6 +45,10 @@ public function deleteById($rateId);
/**
* Search TaxRates
*
+ * This call returns an array of objects, but detailed information about each object’s attributes might not be
+ * included. See http://devdocs.magento.com/codelinks/attributes.html#TaxRateRepositoryInterface to
+ * determine which call to use to get detailed information about all attributes for an object.
+ *
* @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
* @return \Magento\Tax\Api\Data\TaxRateSearchResultsInterface containing Data\TaxRateInterface objects
* @throws \Magento\Framework\Exception\InputException If there is a problem with the input
diff --git a/app/code/Magento/Tax/Api/TaxRuleRepositoryInterface.php b/app/code/Magento/Tax/Api/TaxRuleRepositoryInterface.php
index 29ff3d423e17b..5f477f33bae2e 100644
--- a/app/code/Magento/Tax/Api/TaxRuleRepositoryInterface.php
+++ b/app/code/Magento/Tax/Api/TaxRuleRepositoryInterface.php
@@ -53,6 +53,10 @@ public function deleteById($ruleId);
/**
* Search TaxRules
*
+ * This call returns an array of objects, but detailed information about each object’s attributes might not be
+ * included. See http://devdocs.magento.com/codelinks/attributes.html#TaxRuleRepositoryInterface to
+ * determine which call to use to get detailed information about all attributes for an object.
+ *
* @param \Magento\Framework\Api\SearchCriteria $searchCriteria
* @return \Magento\Tax\Api\Data\TaxRuleSearchResultsInterface containing TaxRuleInterface objects
* @throws \Magento\Framework\Exception\InputException If there is a problem with the input
diff --git a/app/code/Magento/Theme/Model/Theme/ThemeProvider.php b/app/code/Magento/Theme/Model/Theme/ThemeProvider.php
index 0d488e9ad0225..bc6a3a6f27e81 100644
--- a/app/code/Magento/Theme/Model/Theme/ThemeProvider.php
+++ b/app/code/Magento/Theme/Model/Theme/ThemeProvider.php
@@ -17,6 +17,11 @@ class ThemeProvider implements \Magento\Framework\View\Design\Theme\ThemeProvide
*/
protected $themeFactory;
+ /**
+ * @var \Magento\Framework\View\Design\ThemeInterface[]
+ */
+ private $themes;
+
/**
* @param \Magento\Theme\Model\ResourceModel\Theme\CollectionFactory $collectionFactory
* @param \Magento\Theme\Model\ThemeFactory $themeFactory
@@ -34,9 +39,16 @@ public function __construct(
*/
public function getThemeByFullPath($fullPath)
{
+ if (isset($this->themes[$fullPath])) {
+ return $this->themes[$fullPath];
+ }
+
/** @var $themeCollection \Magento\Theme\Model\ResourceModel\Theme\Collection */
$themeCollection = $this->collectionFactory->create();
- return $themeCollection->getThemeByFullPath($fullPath);
+ $item = $themeCollection->getThemeByFullPath($fullPath);
+ $this->themes[$fullPath] = $item;
+
+ return $item;
}
/**
@@ -57,8 +69,16 @@ public function getThemeCustomizations(
*/
public function getThemeById($themeId)
{
+ if (isset($this->themes[$themeId])) {
+ return $this->themes[$themeId];
+ }
/** @var $themeModel \Magento\Framework\View\Design\ThemeInterface */
$themeModel = $this->themeFactory->create();
- return $themeModel->load($themeId);
+ $themeModel->load($themeId);
+ if ($themeModel->getId()) {
+ $this->themes[$themeId] = $themeModel;
+ }
+
+ return $themeModel;
}
}
diff --git a/app/code/Magento/Theme/etc/config.xml b/app/code/Magento/Theme/etc/config.xml
index bd0db014a781b..b55b2c1d2735b 100644
--- a/app/code/Magento/Theme/etc/config.xml
+++ b/app/code/Magento/Theme/etc/config.xml
@@ -62,5 +62,10 @@ Disallow: /*SID=
+
+
+ 1
+
+
diff --git a/app/code/Magento/Theme/view/frontend/web/js/view/messages.js b/app/code/Magento/Theme/view/frontend/web/js/view/messages.js
index 2969fdedd7d41..ef4fe41a3b908 100644
--- a/app/code/Magento/Theme/view/frontend/web/js/view/messages.js
+++ b/app/code/Magento/Theme/view/frontend/web/js/view/messages.js
@@ -5,9 +5,10 @@
define([
'jquery',
'uiComponent',
+ 'underscore',
'Magento_Customer/js/customer-data',
'jquery/jquery-storageapi'
-], function ($, Component, customerData) {
+], function ($, Component, _, customerData) {
'use strict';
return Component.extend({
@@ -15,12 +16,24 @@ define([
cookieMessages: [],
messages: []
},
+
+ /** @inheritdoc */
initialize: function () {
this._super();
this.cookieMessages = $.cookieStorage.get('mage-messages');
- this.messages = customerData.get('messages').extend({disposableCustomerData: 'messages'});
- $.cookieStorage.setConf({path: '/', expires: -1}).set('mage-messages', null);
+ this.messages = customerData.get('messages').extend({
+ disposableCustomerData: 'messages'
+ });
+
+ if (!_.isEmpty(this.messages().messages)) {
+ customerData.set('messages', {});
+ }
+
+ $.cookieStorage.setConf({
+ path: '/',
+ expires: -1
+ }).set('mage-messages', null);
}
});
});
diff --git a/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js b/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js
index e6b8fb53a4441..0c9b5c1e37768 100644
--- a/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js
+++ b/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js
@@ -4,11 +4,12 @@
*/
define([
'./utils',
+ 'underscore',
'jquery',
'jquery/validate',
'jquery/ui',
'mage/translate'
-], function (utils, $) {
+], function (utils, _, $) {
'use strict';
/**
@@ -47,13 +48,13 @@ define([
return {
"min_text_length": [
function (value, params) {
- return value.length == 0 || value.length >= +params;
+ return _.isUndefined(value) || value.length == 0 || value.length >= +params;
},
$.mage.__('Please enter more or equal than {0} symbols.')
],
"max_text_length": [
function (value, params) {
- return value.length <= +params;
+ return !_.isUndefined(value) && value.length <= +params;
},
$.mage.__('Please enter less or equal than {0} symbols.')
],
diff --git a/app/code/Magento/Wishlist/Helper/Data.php b/app/code/Magento/Wishlist/Helper/Data.php
index d64d1a185f0a2..736786e6e30b3 100644
--- a/app/code/Magento/Wishlist/Helper/Data.php
+++ b/app/code/Magento/Wishlist/Helper/Data.php
@@ -446,7 +446,13 @@ public function getSharedAddAllToCartUrl()
*/
protected function _getCartUrlParameters($item)
{
- return ['item' => is_string($item) ? $item : $item->getWishlistItemId()];
+ $params = [
+ 'item' => is_string($item) ? $item : $item->getWishlistItemId(),
+ ];
+ if ($item instanceof \Magento\Wishlist\Model\Item) {
+ $params['qty'] = $item->getQty();
+ }
+ return $params;
}
/**
diff --git a/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php b/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php
index 079aa695b8abb..f2bb346cca407 100644
--- a/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php
+++ b/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php
@@ -124,6 +124,7 @@ public function setUp()
->setMethods([
'getProduct',
'getWishlistItemId',
+ 'getQty',
])
->getMock();
@@ -217,6 +218,7 @@ public function testGetAddToCartParams()
$url = 'result url';
$storeId = 1;
$wishlistItemId = 1;
+ $wishlistItemQty = 1;
$this->wishlistItem->expects($this->once())
->method('getProduct')
@@ -224,6 +226,9 @@ public function testGetAddToCartParams()
$this->wishlistItem->expects($this->once())
->method('getWishlistItemId')
->willReturn($wishlistItemId);
+ $this->wishlistItem->expects($this->once())
+ ->method('getQty')
+ ->willReturn($wishlistItemQty);
$this->product->expects($this->once())
->method('isVisibleInSiteVisibility')
@@ -243,9 +248,13 @@ public function testGetAddToCartParams()
->with('wishlist/index/cart')
->willReturn($url);
+ $expected = [
+ 'item' => $wishlistItemId,
+ 'qty' => $wishlistItemQty,
+ ];
$this->postDataHelper->expects($this->once())
->method('getPostData')
- ->with($url, ['item' => $wishlistItemId])
+ ->with($url, $expected)
->willReturn($url);
$this->assertEquals($url, $this->model->getAddToCartParams($this->wishlistItem));
@@ -256,6 +265,7 @@ public function testGetAddToCartParamsWithReferer()
$url = 'result url';
$storeId = 1;
$wishlistItemId = 1;
+ $wishlistItemQty = 1;
$referer = 'referer';
$refererEncoded = 'referer_encoded';
@@ -265,6 +275,9 @@ public function testGetAddToCartParamsWithReferer()
$this->wishlistItem->expects($this->once())
->method('getWishlistItemId')
->willReturn($wishlistItemId);
+ $this->wishlistItem->expects($this->once())
+ ->method('getQty')
+ ->willReturn($wishlistItemQty);
$this->product->expects($this->once())
->method('isVisibleInSiteVisibility')
@@ -288,9 +301,14 @@ public function testGetAddToCartParamsWithReferer()
->with('wishlist/index/cart')
->willReturn($url);
+ $expected = [
+ 'item' => $wishlistItemId,
+ ActionInterface::PARAM_NAME_URL_ENCODED => $refererEncoded,
+ 'qty' => $wishlistItemQty,
+ ];
$this->postDataHelper->expects($this->once())
->method('getPostData')
- ->with($url, ['item' => $wishlistItemId, ActionInterface::PARAM_NAME_URL_ENCODED => $refererEncoded])
+ ->with($url, $expected)
->willReturn($url);
$this->assertEquals($url, $this->model->getAddToCartParams($this->wishlistItem, true));
@@ -363,6 +381,7 @@ public function testGetSharedAddToCartUrl()
$url = 'result url';
$storeId = 1;
$wishlistItemId = 1;
+ $wishlistItemQty = 1;
$this->wishlistItem->expects($this->once())
->method('getProduct')
@@ -370,6 +389,9 @@ public function testGetSharedAddToCartUrl()
$this->wishlistItem->expects($this->once())
->method('getWishlistItemId')
->willReturn($wishlistItemId);
+ $this->wishlistItem->expects($this->once())
+ ->method('getQty')
+ ->willReturn($wishlistItemQty);
$this->product->expects($this->once())
->method('isVisibleInSiteVisibility')
@@ -383,9 +405,13 @@ public function testGetSharedAddToCartUrl()
->with('wishlist/shared/cart')
->willReturn($url);
+ $exptected = [
+ 'item' => $wishlistItemId,
+ 'qty' => $wishlistItemQty,
+ ];
$this->postDataHelper->expects($this->once())
->method('getPostData')
- ->with($url, ['item' => $wishlistItemId])
+ ->with($url, $exptected)
->willReturn($url);
$this->assertEquals($url, $this->model->getSharedAddToCartUrl($this->wishlistItem));
diff --git a/app/code/Magento/Wishlist/view/frontend/web/wishlist.js b/app/code/Magento/Wishlist/view/frontend/web/wishlist.js
index a4fdc178c704f..0d6e510e5f5e9 100644
--- a/app/code/Magento/Wishlist/view/frontend/web/wishlist.js
+++ b/app/code/Magento/Wishlist/view/frontend/web/wishlist.js
@@ -47,6 +47,7 @@ define([
event.preventDefault();
$.mage.dataPost().postData($(event.currentTarget).data('post-remove'));
}, this))
+ .on('click', this.options.addToCartSelector, $.proxy(this._beforeAddToCart, this))
.on('click', this.options.addAllToCartSelector, $.proxy(this._addAllWItemsToCart, this))
.on('focusin focusout', this.options.commentInputType, $.proxy(this._focusComment, this));
}
@@ -59,6 +60,27 @@ define([
});
},
+ /**
+ * Process data before add to cart
+ *
+ * - update item's qty value.
+ *
+ * @param {Event} event
+ * @private
+ */
+ _beforeAddToCart: function(event) {
+ var elem = $(event.currentTarget),
+ itemId = elem.data(this.options.dataAttribute),
+ qtyName = $.validator.format(this.options.nameFormat, itemId),
+ qtyValue = elem.parents().find('[name="' + qtyName + '"]').val(),
+ params = elem.data('post');
+
+ if (params) {
+ params.data = $.extend({}, params.data, {'qty': qtyValue});
+ elem.data('post', params);
+ }
+ },
+
/**
* Add wish list items to cart.
* @private
diff --git a/dev/tests/functional/composer.json b/dev/tests/functional/composer.json
index 532ccf5e82912..257c29200b6a7 100644
--- a/dev/tests/functional/composer.json
+++ b/dev/tests/functional/composer.json
@@ -1,6 +1,6 @@
{
"require": {
- "magento/mtf": "1.0.0-rc37",
+ "magento/mtf": "2.0.x-dev",
"php": "~5.5.0|~5.6.0|~7.0.0",
"phpunit/phpunit": "4.1.0",
"phpunit/phpunit-selenium": ">=1.2"
diff --git a/dev/tests/functional/etc/repository_replacer.xml b/dev/tests/functional/etc/repository_replacer.xml
new file mode 100644
index 0000000000000..0674f5c7d5d34
--- /dev/null
+++ b/dev/tests/functional/etc/repository_replacer.xml
@@ -0,0 +1,200 @@
+
+
+
+
+
+
+ 4
+
+
+
+
+
+ 113
+
+
+
+ 172
+
+
+
+
+
+ 1
+ 2
+
+
+
+ 1
+
+
+
+
+
+ 1
+
+
+
+ 3
+
+
+
+ 2
+
+
+
+ 0
+
+
+
+ 0
+
+
+
+ 32000
+
+
+
+
+
+ 1
+
+
+
+ 1
+
+
+
+ 0
+
+
+
+
+
+ 1
+
+
+
+
+
+ 1
+
+
+
+ 0
+
+
+
+ 1
+
+
+
+
+
+ 2
+ 2
+
+
+
+ 3
+ 3
+
+
+
+ 0
+
+
+
+
+
+ 1
+ 12
+
+
+
+ 23
+
+
+
+ 2
+ 43
+
+
+
+ 12
+
+
+
+ 43
+
+
+
+ 12
+
+
+
+ 12
+
+
+
+ 43
+
+
+
+ 43
+
+
+
+ 12
+
+
+
+ 12
+
+
+
+ 57
+
+
+
+ 58
+
+
+
+ 57
+
+
+
+ 43
+
+
+
+ 12
+
+
+
+
+
+
+ 1
+
+
+
+
+
+ 1
+
+
+
+
+
+ 1
+
+
+
diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/ModuleResolver/SequenceSorter.php b/dev/tests/functional/lib/Magento/Mtf/Util/ModuleResolver/SequenceSorter.php
new file mode 100644
index 0000000000000..cf8eae8a18629
--- /dev/null
+++ b/dev/tests/functional/lib/Magento/Mtf/Util/ModuleResolver/SequenceSorter.php
@@ -0,0 +1,73 @@
+initObjectManager();
+ }
+ /**
+ * Initialize Magento ObjectManager.
+ *
+ * @return void
+ */
+ protected function initObjectManager()
+ {
+ if (!$this->magentoObjectManager) {
+ $objectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(
+ BP,
+ $_SERVER
+ );
+ $this->magentoObjectManager = $objectManagerFactory->create($_SERVER);
+ }
+ }
+ /**
+ * Get Magento module sequence load.
+ *
+ * @return array
+ */
+ protected function getModuleSequence()
+ {
+ return $this->magentoObjectManager->create(\Magento\Framework\Module\ModuleList\Loader::class)->load();
+ }
+ /**
+ * Sort files according to specified sequence.
+ *
+ * @param array $paths
+ * @return array
+ */
+ public function sort(array $paths)
+ {
+ $sortedPaths = [];
+ $modules = array_keys($this->getModuleSequence());
+ foreach ($modules as $module) {
+ foreach ($paths as $key => $path) {
+ $modulePath = realpath(MTF_TESTS_PATH . str_replace('_', DIRECTORY_SEPARATOR, $module));
+ $path = realpath($path);
+ if (strpos($path, $modulePath) !== false) {
+ $sortedPaths[] = $path;
+ unset($paths[$key]);
+ }
+ }
+ }
+ $sortedPaths = array_merge($sortedPaths, $paths);
+ return $sortedPaths;
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogAttributeSet.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogAttributeSet.xml
index 975d3b3ce8d86..a62bef0680a9e 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogAttributeSet.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogAttributeSet.xml
@@ -8,8 +8,8 @@
+ %id%
Default
- 4
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml
index cb10ceb146c3d..06a22f90f2eb1 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml
@@ -14,7 +14,7 @@
- 113
+ %id%
Quantity
quantity_and_stock_status
Dropdown
@@ -34,7 +34,7 @@
- 172
+ %id%
Tax Class
tax_class_id
Dropdown
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml
index 17c2b5922e5c6..b739978eebf8c 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml
@@ -18,10 +18,10 @@
+ %id%
+ %id%
Default Category
- 1
Yes
- 2
@@ -46,8 +46,8 @@
+ %id%
RootCategory%isolation%
- 1
Yes
Yes
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerGroup.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerGroup.xml
index 2201844677f5d..4e95c89a89ad5 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerGroup.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/CustomerGroup.xml
@@ -15,7 +15,7 @@
- 1
+ %id%
General
- retail_customer
@@ -23,7 +23,7 @@
- 3
+ %id%
Retailer
- retail_customer
@@ -31,7 +31,7 @@
- 2
+ %id%
Wholesale
- retail_customer
@@ -39,12 +39,12 @@
- 0
+ %id%
All Customer Groups
- 0
+ %id%
NOT LOGGED IN
- retail_customer
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml
index 1cff6e7d845d6..b0715e62d7fcd 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/StoreGroup.xml
@@ -8,11 +8,11 @@
+ %id%
- main_website
Main Website Store
- 1
- default_category
diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Website.xml b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Website.xml
index 8b90722866ae9..5c2ec69efca98 100644
--- a/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Website.xml
+++ b/dev/tests/functional/tests/app/Magento/Store/Test/Repository/Website.xml
@@ -8,21 +8,21 @@
+ %id%
Main Website
base
- 1
+ %id%
All Websites
- 0
+ %id%
Main Website
base
0
- 1
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxClass.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxClass.xml
index 35ece9e1fa394..061bc05c07891 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxClass.xml
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxClass.xml
@@ -12,17 +12,17 @@
- 2
+ %id%
+ %id%
Taxable Goods
PRODUCT
- 2
- 3
+ %id%
+ %id%
Retail Customer
CUSTOMER
- 3
@@ -36,9 +36,9 @@
+ %id%
None
PRODUCT
- 0
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.xml
index ac6a00f22ff91..600436dc5f1b7 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.xml
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRate.xml
@@ -16,9 +16,9 @@
- 1
+ %id%
+ %id%
US
- 12
*
US-CA-*-Rate 1
8.2500
@@ -30,9 +30,9 @@
- 2
+ %id%
+ %id%
US
- 43
*
US-NY-*-Rate 1
8.3750
@@ -45,33 +45,33 @@
Tax Rate %isolation%
+ %id%
8.25
United States
90230
- California
+ %id%
Tax Rate %isolation%
8.25
United States
*
- California
Tax Rate %isolation%
+ %id%
8.375
United States
*
- California
Tax Rate %isolation%
+ %id%
8.375
United States
- New York
*
@@ -79,15 +79,15 @@
Tax Rate %isolation%
8.25
United States
- New York
+ %id%
*
US-NY-*-%isolation%
+ %id%
8.1
United States
- New York
*
@@ -96,7 +96,7 @@
8.25
United States
95131
- California
+ %id%
@@ -119,7 +119,7 @@
90001
96162
United States
- California
+ %id%
15.5
@@ -127,7 +127,7 @@
TaxIdentifier%isolation%
*
United States
- Texas
+ %id%
20
@@ -135,7 +135,7 @@
TaxIdentifier%isolation%
84001
United States
- Utah
+ %id%
20
@@ -143,7 +143,7 @@
TaxIdentifier%isolation%
*
United States
- Texas
+ %id%
10
@@ -151,7 +151,7 @@
TaxIdentifier%isolation%
*
United States
- New York
+ %id%
20
@@ -159,7 +159,7 @@
TaxIdentifier%isolation%
*
United States
- California
+ %id%
30
diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.xml
index 69c8f0d945760..33f0a7105ef34 100644
--- a/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.xml
+++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Repository/TaxRule.xml
@@ -32,7 +32,7 @@
Tax Rule %isolation%
-
-
- US-CA-Rate_1
+ - us_ca_rate_8_25_no_zip
- us_ny_rate_8_1
diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml b/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml
index 7aa989352a656..25b812bf77665 100644
--- a/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml
+++ b/dev/tests/functional/tests/app/Magento/User/Test/Repository/User.xml
@@ -8,13 +8,13 @@
+ %id%
admin
FirstName%isolation%
LastName%isolation%
email%isolation%@example.com
123123q
123123q
- 1
%current_password%
diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php
index 03abeaf837ff7..e2d835c07d4b2 100644
--- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php
+++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php
@@ -62,4 +62,97 @@ public function testPrepareProductIndexForBundleProduct()
$result = $this->connectionMock->fetchAll($select);
$this->assertCount(1, $result);
}
+
+ /**
+ * Test that having valid buyRequest it can be successfully prepared fro shopping cart
+ *
+ * @magentoDataFixture Magento/Bundle/_files/product_with_multiple_options.php
+ * @magentoAppArea frontend
+ * @magentoAppIsolation enabled
+ */
+ public function testPrepareForCart()
+ {
+ /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
+ $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+ $product = $productRepository->get('bundle-product');
+
+ /** @var \Magento\Bundle\Api\ProductOptionRepositoryInterface $optionsRepository */
+ $optionsRepository = $this->objectManager->create(\Magento\Bundle\Api\ProductOptionRepositoryInterface::class);
+ $options = $optionsRepository->getList($product->getSku());
+
+ $data = [
+ 'id' => '10',
+ 'product' => '3',
+ 'selected_configurable_option' => '',
+ 'related_product' => '',
+ 'bundle_option' => [],
+ 'bundle_option_qty' => [],
+ 'qty' => '1',
+ 'options' => [],
+ 'reset_count' => true,
+ ];
+
+ foreach ($options as $option) {
+ /** @var \Magento\Bundle\Api\Data\LinkInterface $link */
+ $link = current($option->getProductLinks());
+ $data['bundle_option'][$option->getOptionId()] = $link->getId();
+ $data['bundle_option_qty'][$option->getOptionId()] = 1;
+ }
+
+ $request = $this->objectManager->create(\Magento\Framework\DataObject::class, ['data' => $data]);
+ /** @var \Magento\Bundle\Model\Product\Type $typeInstance */
+ $typeInstance = $product->getTypeInstance();
+
+ $result = $typeInstance->prepareForCart($request, $product);
+ $this->assertEquals(count($data['bundle_option']) + 1, count($result), 'Incorrect product count');
+ }
+
+ /**
+ * Test that having invalid selection option in buyRequest
+ * prepareForCart method will return meaningful error message
+ *
+ * @magentoDataFixture Magento/Bundle/_files/product_with_multiple_options.php
+ * @magentoAppArea frontend
+ * @magentoAppIsolation enabled
+ */
+ public function testPrepareForCartWithUnavailableOption()
+ {
+ /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
+ $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+ $product = $productRepository->get('bundle-product');
+
+ /** @var \Magento\Bundle\Api\ProductOptionRepositoryInterface $optionsRepository */
+ $optionsRepository = $this->objectManager->create(\Magento\Bundle\Api\ProductOptionRepositoryInterface::class);
+ $options = $optionsRepository->getList($product->getSku());
+
+ $data = [
+ 'id' => '10',
+ 'product' => '3',
+ 'selected_configurable_option' => '',
+ 'related_product' => '',
+ 'bundle_option' => [],
+ 'bundle_option_qty' => [],
+ 'qty' => '1',
+ 'options' => [],
+ 'reset_count' => true,
+ ];
+
+ $option = null;
+ foreach ($options as $option) {
+ /** @var \Magento\Bundle\Api\Data\LinkInterface $link */
+ $link = current($option->getProductLinks());
+ $data['bundle_option'][$option->getOptionId()] = $link->getId();
+ $data['bundle_option_qty'][$option->getOptionId()] = 1;
+ }
+
+ /** Set latest option selection to unavailable option */
+ $data['bundle_option'][$option->getOptionId()] = 300;
+
+ $buyRequest = $this->objectManager->create(\Magento\Framework\DataObject::class, ['data' => $data]);
+ /** @var \Magento\Bundle\Model\Product\Type $typeInstance */
+ $typeInstance = $product->getTypeInstance();
+
+ $result = $typeInstance->prepareForCart($buyRequest, $product);
+ $this->assertEquals('The options you selected are not available.', $result);
+ }
}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ImageTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ImageTest.php
index 04dac68782f81..9f2196ac19ca1 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ImageTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ImageTest.php
@@ -46,7 +46,7 @@ public function testSaveFilePlaceholder($model)
public function testGetUrlPlaceholder($model)
{
$this->assertStringMatchesFormat(
- 'http://localhost/pub/static/frontend/%s/Magento_Catalog/images/product/placeholder/image.jpg',
+ 'http://localhost/pub/static/%s/frontend/%s/Magento_Catalog/images/product/placeholder/image.jpg',
$model->getUrl()
);
}
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
index 84023f86cbcd2..3fd3419b5554e 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php
@@ -14,13 +14,14 @@
*/
namespace Magento\CatalogImportExport\Model\Import;
+use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Framework\App\Bootstrap;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\ImportExport\Model\Import;
/**
* Class ProductTest
- *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @magentoDataFixtureBeforeTransaction Magento/Catalog/_files/enable_reindex_schedule.php
*/
class ProductTest extends \PHPUnit_Framework_TestCase
@@ -946,4 +947,62 @@ public function testValidateUrlKeysMultipleStores()
$this->assertTrue($errors->getErrorsCount() == 0);
}
+
+ /**
+ * @magentoDataFixture Magento/Store/_files/website.php
+ * @magentoDataFixture Magento/Store/_files/core_fixturestore.php
+ * @magentoDbIsolation enabled
+ * @magentoAppIsolation enabled
+ */
+ public function testProductWithMultipleStoresInDifferentBunches()
+ {
+ $products = [
+ 'simple1',
+ 'simple2',
+ 'simple3'
+ ];
+
+ $importExportData = $this->getMockBuilder(\Magento\ImportExport\Helper\Data::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $importExportData->expects($this->atLeastOnce())
+ ->method('getBunchSize')
+ ->willReturn(1);
+ $this->_model = $this->objectManager->create(
+ \Magento\CatalogImportExport\Model\Import\Product::class,
+ ['importExportData' => $importExportData]
+ );
+
+ $filesystem = $this->objectManager->create(\Magento\Framework\Filesystem::class);
+ $directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT);
+ $source = $this->objectManager->create(
+ \Magento\ImportExport\Model\Import\Source\Csv::class,
+ [
+ 'file' => __DIR__ . '/_files/products_to_import_with_multiple_store.csv',
+ 'directory' => $directory
+ ]
+ );
+ $errors = $this->_model->setParameters(
+ ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product']
+ )->setSource(
+ $source
+ )->validateData();
+
+ $this->assertTrue($errors->getErrorsCount() == 0);
+
+ $this->_model->importData();
+ $productCollection = $this->objectManager
+ ->create(\Magento\Catalog\Model\ResourceModel\Product\Collection::class);
+ $this->assertCount(3, $productCollection->getItems());
+ $actualProductSkus = array_map(
+ function(ProductInterface $item) {
+ return $item->getSku();
+ },
+ $productCollection->getItems()
+ );
+ $this->assertEquals(
+ $products,
+ array_values($actualProductSkus)
+ );
+ }
}
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_multiple_store.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_multiple_store.csv
new file mode 100644
index 0000000000000..a4ad5adb7b0f4
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_multiple_store.csv
@@ -0,0 +1,6 @@
+sku,product_type,store_view_code,name,price,attribute_set_code,categories
+simple1,simple,fixturestore,"simple 1",25,Default,"Default Category/Category 1"
+simple1,simple,,"simple 1",25,Default,"Default Category/Category 1"
+simple2,simple,fixturestore,"simple 2",34,Default,"Default Category/Category 1"
+simple2,simple,,"simple 2",34,Default,"Default Category/Category 1"
+simple3,simple,,"simple 3",58,Default,"Default Category/Category 1"
diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/ConfigTest.php
index 07b55f5e9aeaf..fdb63a875282e 100644
--- a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/ConfigTest.php
+++ b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/ConfigTest.php
@@ -42,7 +42,7 @@ public function testGetConfig()
public function testGetConfigCssUrls()
{
$config = $this->_model->getConfig();
- $publicPathPattern = 'http://localhost/pub/static/adminhtml/Magento/backend/en_US/mage/%s';
+ $publicPathPattern = 'http://localhost/pub/static/%s/adminhtml/Magento/backend/en_US/mage/%s';
$this->assertStringMatchesFormat($publicPathPattern, $config->getPopupCss());
$this->assertStringMatchesFormat($publicPathPattern, $config->getContentCss());
}
diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php
index a3baf43c54949..523058759fa87 100644
--- a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php
+++ b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/StorageTest.php
@@ -57,7 +57,7 @@ public function testGetFilesCollection()
$this->assertInstanceOf('Magento\Framework\DataObject', $item);
$this->assertStringEndsWith('/1.swf', $item->getUrl());
$this->assertStringMatchesFormat(
- 'http://%s/static/adminhtml/%s/%s/Magento_Cms/images/placeholder_thumbnail.jpg',
+ 'http://%s/static/%s/adminhtml/%s/%s/Magento_Cms/images/placeholder_thumbnail.jpg',
$item->getThumbUrl()
);
return;
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
index 0b4c736b40991..eb942ad392d19 100644
--- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/ConfigurableTest.php
@@ -239,7 +239,8 @@ public function testGetSelectedAttributesInfo()
$this->_product->addCustomOption('attributes', serialize([$attribute['attribute_id'] => $optionValueId]));
$info = $this->_model->getSelectedAttributesInfo($this->_product);
- $this->assertEquals([['label' => 'Test Configurable', 'value' => 'Option 1']], $info);
+ $this->assertEquals('Test Configurable', $info[0]['label']);
+ $this->assertEquals('Option 1', $info[0]['value']);
}
/**
@@ -259,7 +260,8 @@ public function testGetSelectedAttributesInfoForStore()
$attribute->getProductAttribute()->setStoreLabel('store label');
$info = $this->_model->getSelectedAttributesInfo($this->_product);
- $this->assertEquals([['label' => 'store label', 'value' => 'Option 1']], $info);
+ $this->assertEquals('store label', $info[0]['label']);
+ $this->assertEquals('Option 1', $info[0]['value']);
}
/**
@@ -302,10 +304,8 @@ public function testGetOrderOptions()
$result = $this->_model->getOrderOptions($this->_product);
$this->assertArrayHasKey('info_buyRequest', $result);
$this->assertArrayHasKey('attributes_info', $result);
- $this->assertEquals(
- [['label' => 'Test Configurable', 'value' => 'Option 1']],
- $result['attributes_info']
- );
+ $this->assertEquals('Test Configurable', $result['attributes_info'][0]['label']);
+ $this->assertEquals('Option 1', $result['attributes_info'][0]['value']);
$this->assertArrayHasKey('product_calculations', $result);
$this->assertArrayHasKey('shipment_type', $result);
$this->assertEquals(
diff --git a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php
index 6a101a201051f..8cb9e4a38bfe0 100644
--- a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php
+++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/CustomerTest.php
@@ -112,11 +112,8 @@ public function testImportData()
/** @var $objectManager \Magento\TestFramework\ObjectManager */
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
- $existingCustomer = $objectManager->get(
- 'Magento\Framework\Registry'
- )->registry(
- '_fixture/Magento_ImportExport_Customer'
- );
+ $existingCustomer = $objectManager->get('Magento\Framework\Registry')
+ ->registry('_fixture/Magento_ImportExport_Customer');
$updatedCustomer = $customers[$existingCustomer->getId()];
@@ -137,6 +134,12 @@ public function testImportData()
$updatedCustomer->getCreatedAt(),
'Creation date must be changed'
);
+
+ $this->assertEquals(
+ $existingCustomer->getGender(),
+ $updatedCustomer->getGender(),
+ 'Gender must be not changed'
+ );
}
/**
diff --git a/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php b/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php
index f330749fa6418..a4ee39948e118 100644
--- a/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php
+++ b/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php
@@ -283,6 +283,7 @@ public function cssDirectiveDataProvider()
* @magentoComponentsDir Magento/Email/Model/_files/design
* @magentoAppIsolation enabled
* @magentoDbIsolation enabled
+ * @magentoConfigFixture default_store dev/static/sign 0
* @dataProvider inlinecssDirectiveDataProvider
*
* @param string $templateText
diff --git a/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php b/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php
index a47c1aa0d8d9a..dab0750661eec 100644
--- a/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php
+++ b/dev/tests/integration/testsuite/Magento/Email/Model/TemplateTest.php
@@ -122,7 +122,7 @@ public function testGetProcessedTemplate()
->getArea(Area::AREA_FRONTEND)
->load();
- $expectedViewUrl = 'static/frontend/Magento/blank/en_US/Magento_Theme/favicon.ico';
+ $expectedViewUrl = '/frontend/Magento/blank/en_US/Magento_Theme/favicon.ico';
$this->model->setDesignConfig([
'area' => 'frontend',
'store' => $this->objectManager->get('Magento\Store\Model\StoreManagerInterface')
@@ -578,7 +578,6 @@ public function testGetProcessedTemplateSubject()
->getArea(Area::AREA_FRONTEND)
->load();
- $expectedViewUrl = 'static/frontend/Magento/blank/en_US/Magento_Theme/favicon.ico';
$this->model->setTemplateSubject('{{view url="Magento_Theme::favicon.ico"}}');
$this->model->setDesignConfig([
'area' => 'frontend',
@@ -588,10 +587,16 @@ public function testGetProcessedTemplateSubject()
]);
$this->setNotDefaultThemeForFixtureStore();
- $this->assertStringEndsNotWith($expectedViewUrl, $this->model->getProcessedTemplateSubject([]));
+ $this->assertStringMatchesFormat(
+ '%s/frontend/Magento/luma/en_US/Magento_Theme/favicon.ico',
+ $this->model->getProcessedTemplateSubject([])
+ );
$this->setDefaultThemeForFixtureStore();
- $this->assertStringEndsWith($expectedViewUrl, $this->model->getProcessedTemplateSubject([]));
+ $this->assertStringMatchesFormat(
+ '%s/frontend/Magento/blank/en_US/Magento_Theme/favicon.ico',
+ $this->model->getProcessedTemplateSubject([])
+ );
}
/**
@@ -605,7 +610,7 @@ public function testGetDefaultEmailLogo()
->load();
$this->assertStringEndsWith(
- 'static/frontend/Magento/luma/en_US/Magento_Email/logo_email.png',
+ '/frontend/Magento/luma/en_US/Magento_Email/logo_email.png',
$this->model->getDefaultEmailLogo()
);
}
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/Asset/MinifierTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/Asset/MinifierTest.php
index 3cfeb69f24532..c94677f98f5f7 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/Asset/MinifierTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/Asset/MinifierTest.php
@@ -14,6 +14,7 @@
*
* @magentoComponentsDir Magento/Framework/View/_files/static/theme
* @magentoDbIsolation enabled
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class MinifierTest extends \PHPUnit_Framework_TestCase
{
@@ -139,43 +140,44 @@ protected function _testCssMinification($requestedUri, $assertionCallback)
}
/**
- * @magentoConfigFixture current_store dev/css/minify_files 1
+ * @magentoConfigFixture current_store dev/css/minify_files 0
+ * @magentoAppIsolation enabled
*/
- public function testCssMinification()
+ public function testCssMinificationOff()
{
$this->_testCssMinification(
- '/frontend/FrameworkViewMinifier/default/en_US/css/styles.min.css',
+ '/frontend/FrameworkViewMinifier/default/en_US/css/styles.css',
function ($path) {
- $this->assertEquals(
+ $content = file_get_contents($path);
+ $this->assertNotEmpty($content);
+ $this->assertContains('FrameworkViewMinifier/frontend', $content);
+ $this->assertNotEquals(
file_get_contents(
dirname(__DIR__)
. '/_files/static/expected/styles.magento.min.css'
),
- file_get_contents($path),
- 'Minified files are not equal or minification did not work for requested CSS'
+ $content,
+ 'CSS is minified when minification turned off'
);
}
);
}
/**
- * @magentoConfigFixture current_store dev/css/minify_files 0
+ * @magentoConfigFixture current_store dev/css/minify_files 1
*/
- public function testCssMinificationOff()
+ public function testCssMinification()
{
$this->_testCssMinification(
- '/frontend/FrameworkViewMinifier/default/en_US/css/styles.css',
+ '/frontend/FrameworkViewMinifier/default/en_US/css/styles.min.css',
function ($path) {
- $content = file_get_contents($path);
- $this->assertNotEmpty($content);
- $this->assertContains('FrameworkViewMinifier/frontend', $content);
- $this->assertNotEquals(
+ $this->assertEquals(
file_get_contents(
dirname(__DIR__)
. '/_files/static/expected/styles.magento.min.css'
),
- $content,
- 'CSS is minified when minification turned off'
+ file_get_contents($path),
+ 'Minified files are not equal or minification did not work for requested CSS'
);
}
);
@@ -233,13 +235,13 @@ public function testDeploymentWithMinifierEnabled()
]
));
- /** @var \Magento\Deploy\Model\Deployer $deployer */
+ /** @var \Magento\Deploy\Model\Deploy\LocaleDeploy $deployer */
$deployer = $this->objectManager->create(
- 'Magento\Deploy\Model\Deployer',
- ['filesUtil' => $filesUtil, 'output' => $output, 'isDryRun' => false]
+ \Magento\Deploy\Model\Deploy\LocaleDeploy::class,
+ ['filesUtil' => $filesUtil, 'output' => $output]
);
- $deployer->deploy($omFactory, ['en_US']);
+ $deployer->deploy('frontend', 'FrameworkViewMinifier/default', 'en_US', []);
$this->assertFileExists($fileToBePublished);
$this->assertEquals(
diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/Element/AbstractBlockTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/Element/AbstractBlockTest.php
index de6031e9db0e3..260311b48b1ec 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/View/Element/AbstractBlockTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/View/Element/AbstractBlockTest.php
@@ -477,7 +477,10 @@ public function testGetUrl()
public function testGetViewFileUrl()
{
$actualResult = $this->_block->getViewFileUrl('css/styles.css');
- $this->assertStringMatchesFormat('http://localhost/pub/static/frontend/%s/en_US/css/styles.css', $actualResult);
+ $this->assertStringMatchesFormat(
+ 'http://localhost/pub/static/%s/frontend/%s/en_US/css/styles.css',
+ $actualResult
+ );
}
public function testGetModuleName()
diff --git a/dev/tests/integration/testsuite/Magento/Review/Controller/ProductTest.php b/dev/tests/integration/testsuite/Magento/Review/Controller/ProductTest.php
index 57cf616fd7c7a..967650a85271e 100644
--- a/dev/tests/integration/testsuite/Magento/Review/Controller/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/Review/Controller/ProductTest.php
@@ -16,7 +16,7 @@ public function testListActionDesign($productId, $expectedDesign)
$this->getRequest()->setParam('id', $productId);
$this->dispatch('review/product/listAction');
$result = $this->getResponse()->getBody();
- $this->assertContains("static/frontend/{$expectedDesign}/en_US/Magento_Theme/favicon.ico", $result);
+ $this->assertContains("/frontend/{$expectedDesign}/en_US/Magento_Theme/favicon.ico", $result);
}
/**
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/OrderItemTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/OrderItemTest.php
new file mode 100644
index 0000000000000..e23ecd978eb7c
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/OrderItemTest.php
@@ -0,0 +1,37 @@
+objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+ }
+
+ /**
+ * Verify that serialized order item data was unserialized after load
+ *
+ * @magentoDataFixture Magento/Catalog/_files/order_item_with_product_and_custom_options.php
+ */
+ public function testGetOrderItem()
+ {
+ /** @var \Magento\Sales\Model\Order $order */
+ $order = $this->objectManager->create(\Magento\Sales\Model\Order::class);
+ $order->loadByIncrementId('100000001');
+ $items = $order->getItemsCollection();
+ $this->assertNotEquals(0, $items->getSize());
+ foreach ($items as $item) {
+ $info = $item->getDataByKey('product_options');
+ $this->assertTrue(is_array($info));
+ }
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/Rule/CollectionTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/Rule/CollectionTest.php
index ae02d11a597cf..9f8eccf92676c 100644
--- a/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/Rule/CollectionTest.php
+++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/ResourceModel/Rule/CollectionTest.php
@@ -38,15 +38,15 @@ public function testSetValidationFilter($couponCode, $expectedItems)
public function setValidationFilterDataProvider()
{
return [
- 'Check type COUPON' => ['coupon_code', ['#1', '#5']],
+ 'Check type COUPON' => ['coupon_code', ['#1', '#2', '#5']],
'Check type NO_COUPON' => ['', ['#2', '#5']],
- 'Check type COUPON_AUTO' => ['coupon_code_auto', ['#4', '#5']],
- 'Check result with auto generated coupon' => ['autogenerated_3_1', ['#3', '#5']],
+ 'Check type COUPON_AUTO' => ['coupon_code_auto', ['#2', '#4', '#5']],
+ 'Check result with auto generated coupon' => ['autogenerated_3_1', ['#2', '#3', '#5']],
'Check result with non actual previously generated coupon' => [
'autogenerated_2_1',
['#2', '#5'],
],
- 'Check result with wrong code' => ['wrong_code', ['#5']]
+ 'Check result with wrong code' => ['wrong_code', ['#2', '#5']]
];
}
diff --git a/dev/tests/integration/testsuite/Magento/Variable/Model/Variable/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Variable/Model/Variable/ConfigTest.php
index 36cdd82450ec5..4828cb68190e1 100644
--- a/dev/tests/integration/testsuite/Magento/Variable/Model/Variable/ConfigTest.php
+++ b/dev/tests/integration/testsuite/Magento/Variable/Model/Variable/ConfigTest.php
@@ -21,15 +21,16 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
- 'Magento\Variable\Model\Variable\Config'
+ \Magento\Variable\Model\Variable\Config::class
);
}
public function testGetWysiwygJsPluginSrc()
{
$src = $this->_model->getWysiwygJsPluginSrc();
- $this->assertStringStartsWith('http://localhost/pub/static/adminhtml/Magento/backend/en_US/mage/adminhtml/',
- $src);
- $this->assertStringEndsWith('editor_plugin.js', $src);
+ $this->assertStringMatchesFormat(
+ 'http://localhost/pub/static/%s/adminhtml/Magento/backend/en_US/mage/adminhtml/%s/editor_plugin.js',
+ $src
+ );
}
}
diff --git a/dev/tests/integration/testsuite/Magento/Widget/Model/Widget/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Widget/Model/Widget/ConfigTest.php
index 42143e8a4ce4d..3e13f8daf5a60 100644
--- a/dev/tests/integration/testsuite/Magento/Widget/Model/Widget/ConfigTest.php
+++ b/dev/tests/integration/testsuite/Magento/Widget/Model/Widget/ConfigTest.php
@@ -43,8 +43,10 @@ public function testGetPluginSettings()
$this->assertArrayHasKey('widget_window_url', $settings);
$jsFilename = $settings['widget_plugin_src'];
- $this->assertStringStartsWith('http://localhost/pub/static/adminhtml/Magento/backend/en_US/', $jsFilename);
- $this->assertStringEndsWith('editor_plugin.js', $jsFilename);
+ $this->assertStringMatchesFormat(
+ 'http://localhost/pub/static/%s/adminhtml/Magento/backend/en_US/%s/editor_plugin.js',
+ $jsFilename
+ );
$this->assertInternalType('array', $settings['widget_placeholders']);
diff --git a/lib/internal/Magento/Framework/App/Cache/Type/Dummy.php b/lib/internal/Magento/Framework/App/Cache/Type/Dummy.php
new file mode 100644
index 0000000000000..ea6a3c3e92e7e
--- /dev/null
+++ b/lib/internal/Magento/Framework/App/Cache/Type/Dummy.php
@@ -0,0 +1,67 @@
+getConnectionByName($connectionName);
}
+ /**
+ * @param string $resourceName
+ * @return void
+ */
+ public function closeConnection($resourceName = self::DEFAULT_CONNECTION)
+ {
+ $processConnectionName = $this->getProcessConnectionName($this->config->getConnectionName($resourceName));
+ if (isset($this->connections[$processConnectionName])) {
+ $this->connections[$processConnectionName] = null;
+ }
+ }
+
/**
* Retrieve connection by $connectionName
*
@@ -101,8 +113,9 @@ public function getConnection($resourceName = self::DEFAULT_CONNECTION)
*/
public function getConnectionByName($connectionName)
{
- if (isset($this->connections[$connectionName])) {
- return $this->connections[$connectionName];
+ $processConnectionName = $this->getProcessConnectionName($connectionName);
+ if (isset($this->connections[$processConnectionName])) {
+ return $this->connections[$processConnectionName];
}
$connectionConfig = $this->deploymentConfig->get(
@@ -115,10 +128,19 @@ public function getConnectionByName($connectionName)
throw new \DomainException('Connection "' . $connectionName . '" is not defined');
}
- $this->connections[$connectionName] = $connection;
+ $this->connections[$processConnectionName] = $connection;
return $connection;
}
+ /**
+ * @param string $connectionName
+ * @return string
+ */
+ private function getProcessConnectionName($connectionName)
+ {
+ return $connectionName . '_process_' . getmypid();
+ }
+
/**
* Get resource table name, validated by db adapter
*
diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/ViewFactoryTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/ViewFactoryTest.php
new file mode 100644
index 0000000000000..7184c713bbd48
--- /dev/null
+++ b/lib/internal/Magento/Framework/Config/Test/Unit/ViewFactoryTest.php
@@ -0,0 +1,94 @@
+objectManager = $this->getMock(\Magento\Framework\ObjectManagerInterface::class);
+ $this->model = new \Magento\Framework\Config\ViewFactory($this->objectManager);
+ $this->theme = $this->getMock(\Magento\Framework\View\Design\ThemeInterface::class);
+ $this->view = $this->getMock(\Magento\Framework\Config\View::class, [], [], '', false);
+ }
+
+ public function testCreate()
+ {
+ $this->objectManager->expects($this->once())
+ ->method('create')
+ ->with(\Magento\Framework\Config\View::class, [])
+ ->willReturn($this->view);
+ $this->assertEquals($this->view, $this->model->create());
+ }
+
+ public function testCreateWithArguments()
+ {
+ /** @var \Magento\Theme\Model\View\Design|\PHPUnit_Framework_MockObject_MockObject $design */
+ $design = $this->getMock(\Magento\Theme\Model\View\Design::class, [], [], '', false);
+ $design->expects($this->once())
+ ->method('setDesignTheme')
+ ->with($this->theme, self::AREA);
+
+ /** @var \Magento\Framework\Config\FileResolver|\PHPUnit_Framework_MockObject_MockObject $fileResolver */
+ $fileResolver = $this->getMock(\Magento\Framework\Config\FileResolver::class, [], [], '', false);
+
+ $valueMap = [
+ [\Magento\Theme\Model\View\Design::class, [], $design],
+ [\Magento\Framework\Config\FileResolver::class, ['designInterface' => $design], $fileResolver],
+ [\Magento\Framework\Config\View::class, ['fileResolver' => $fileResolver], $this->view],
+ ];
+ $this->objectManager->expects($this->exactly(3))
+ ->method('create')
+ ->willReturnMap($valueMap);
+
+ $this->assertEquals($this->view, $this->model->create($this->getArguments()));
+ }
+
+ /**
+ * @expectedException \Magento\Framework\Exception\LocalizedException
+ * @expectedExceptionMessage wrong theme doesn't implement ThemeInterface
+ */
+ public function testCreateException()
+ {
+ $this->model->create([
+ 'themeModel' => 'wrong theme',
+ 'area' => self::AREA
+ ]);
+ }
+
+ /**
+ * @return array
+ */
+ protected function getArguments()
+ {
+ return [
+ 'themeModel' => $this->theme,
+ 'area' => self::AREA
+ ];
+ }
+}
diff --git a/lib/internal/Magento/Framework/Config/ViewFactory.php b/lib/internal/Magento/Framework/Config/ViewFactory.php
index 2df147b0fa626..7adff4f50cf59 100644
--- a/lib/internal/Magento/Framework/Config/ViewFactory.php
+++ b/lib/internal/Magento/Framework/Config/ViewFactory.php
@@ -26,12 +26,38 @@ public function __construct(ObjectManagerInterface $objectManager)
}
/**
+ * Create new view object
+ *
+ * @param array $arguments
* @return \Magento\Framework\Config\View
+ * @throws \Magento\Framework\Exception\LocalizedException
*/
- public function create()
+ public function create(array $arguments = [])
{
+ $viewConfigArguments = [];
+
+ if (isset($arguments['themeModel']) && isset($arguments['area'])) {
+ if (!($arguments['themeModel'] instanceof \Magento\Framework\View\Design\ThemeInterface)) {
+ throw new \Magento\Framework\Exception\LocalizedException(
+ new \Magento\Framework\Phrase('%1 doesn\'t implement ThemeInterface', [$arguments['themeModel']])
+ );
+ }
+ /** @var \Magento\Theme\Model\View\Design $design */
+ $design = $this->objectManager->create(\Magento\Theme\Model\View\Design::class);
+ $design->setDesignTheme($arguments['themeModel'], $arguments['area']);
+ /** @var \Magento\Framework\Config\FileResolver $fileResolver */
+ $fileResolver = $this->objectManager->create(
+ \Magento\Framework\Config\FileResolver::class,
+ [
+ 'designInterface' => $design,
+ ]
+ );
+ $viewConfigArguments['fileResolver'] = $fileResolver;
+ }
+
return $this->objectManager->create(
- 'Magento\Framework\Config\View'
+ \Magento\Framework\Config\View::class,
+ $viewConfigArguments
);
}
}
diff --git a/lib/internal/Magento/Framework/Console/Cli.php b/lib/internal/Magento/Framework/Console/Cli.php
index fa5857d472794..35ee879381742 100644
--- a/lib/internal/Magento/Framework/Console/Cli.php
+++ b/lib/internal/Magento/Framework/Console/Cli.php
@@ -21,6 +21,12 @@
*/
class Cli extends SymfonyApplication
{
+ /**
+ * Cli exit codes
+ */
+ const RETURN_SUCCESS = 0;
+ const RETURN_FAILURE = 1;
+
/**
* Name of input option
*/
diff --git a/lib/internal/Magento/Framework/Css/PreProcessor/Adapter/Less/Processor.php b/lib/internal/Magento/Framework/Css/PreProcessor/Adapter/Less/Processor.php
index 6387ac46e038c..7883586d0b7e5 100644
--- a/lib/internal/Magento/Framework/Css/PreProcessor/Adapter/Less/Processor.php
+++ b/lib/internal/Magento/Framework/Css/PreProcessor/Adapter/Less/Processor.php
@@ -16,6 +16,7 @@
/**
* Class Processor
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Processor implements ContentProcessorInterface
{
@@ -81,9 +82,11 @@ public function processContent(File $asset)
}
$tmpFilePath = $this->temporaryFile->createFile($path, $content);
- $parser->parseFile($tmpFilePath, '');
+ gc_disable();
+ $parser->parseFile($tmpFilePath, '');
$content = $parser->getCss();
+ gc_enable();
if (trim($content) === '') {
$errorMessage = PHP_EOL . self::ERROR_MESSAGE_PREFIX . PHP_EOL . $path;
diff --git a/lib/internal/Magento/Framework/Css/PreProcessor/Instruction/MagentoImport.php b/lib/internal/Magento/Framework/Css/PreProcessor/Instruction/MagentoImport.php
index a07c7eea16aeb..6da9d71142453 100644
--- a/lib/internal/Magento/Framework/Css/PreProcessor/Instruction/MagentoImport.php
+++ b/lib/internal/Magento/Framework/Css/PreProcessor/Instruction/MagentoImport.php
@@ -5,15 +5,18 @@
*/
namespace Magento\Framework\Css\PreProcessor\Instruction;
+use Magento\Framework\App\ObjectManager;
use Magento\Framework\Css\PreProcessor\ErrorHandlerInterface;
use Magento\Framework\View\Asset\File\FallbackContext;
use Magento\Framework\View\Asset\LocalInterface;
use Magento\Framework\View\Asset\PreProcessorInterface;
+use Magento\Framework\View\Design\Theme\ThemeProviderInterface;
use Magento\Framework\View\DesignInterface;
use Magento\Framework\View\File\CollectorInterface;
/**
* @magento_import instruction preprocessor
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class MagentoImport implements PreProcessorInterface
{
@@ -45,9 +48,15 @@ class MagentoImport implements PreProcessorInterface
/**
* @var \Magento\Framework\View\Design\Theme\ListInterface
+ * @deprecated
*/
protected $themeList;
+ /**
+ * @var ThemeProviderInterface
+ */
+ private $themeProvider;
+
/**
* @param DesignInterface $design
* @param CollectorInterface $fileSource
@@ -120,8 +129,23 @@ protected function getTheme(LocalInterface $asset)
{
$context = $asset->getContext();
if ($context instanceof FallbackContext) {
- return $this->themeList->getThemeByFullPath($context->getAreaCode() . '/' . $context->getThemePath());
+ return $this->getThemeProvider()->getThemeByFullPath(
+ $context->getAreaCode() . '/' . $context->getThemePath()
+ );
}
return $this->design->getDesignTheme();
}
+
+ /**
+ * @return ThemeProviderInterface
+ * @deprecated
+ */
+ private function getThemeProvider()
+ {
+ if (null === $this->themeProvider) {
+ $this->themeProvider = ObjectManager::getInstance()->get(ThemeProviderInterface::class);
+ }
+
+ return $this->themeProvider;
+ }
}
diff --git a/lib/internal/Magento/Framework/Css/Test/Unit/PreProcessor/Instruction/MagentoImportTest.php b/lib/internal/Magento/Framework/Css/Test/Unit/PreProcessor/Instruction/MagentoImportTest.php
index ddaec4ef17e8b..a4f1c62d1bce5 100644
--- a/lib/internal/Magento/Framework/Css/Test/Unit/PreProcessor/Instruction/MagentoImportTest.php
+++ b/lib/internal/Magento/Framework/Css/Test/Unit/PreProcessor/Instruction/MagentoImportTest.php
@@ -8,6 +8,13 @@
namespace Magento\Framework\Css\Test\Unit\PreProcessor\Instruction;
+use Magento\Framework\Css\PreProcessor\Instruction\MagentoImport;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Magento\Framework\View\Design\Theme\ThemeProviderInterface;
+
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
class MagentoImportTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -38,7 +45,7 @@ class MagentoImportTest extends \PHPUnit_Framework_TestCase
/**
* @var \Magento\Framework\View\Design\Theme\ListInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- private $themeList;
+ private $themeProvider;
/**
* @var \Magento\Framework\Css\PreProcessor\Instruction\Import
@@ -55,14 +62,16 @@ protected function setUp()
$this->asset = $this->getMock('\Magento\Framework\View\Asset\File', [], [], '', false);
$this->asset->expects($this->any())->method('getContentType')->will($this->returnValue('css'));
$this->assetRepo = $this->getMock('\Magento\Framework\View\Asset\Repository', [], [], '', false);
- $this->themeList = $this->getMockForAbstractClass('\Magento\Framework\View\Design\Theme\ListInterface');
- $this->object = new \Magento\Framework\Css\PreProcessor\Instruction\MagentoImport(
- $this->design,
- $this->fileSource,
- $this->errorHandler,
- $this->assetRepo,
- $this->themeList
- );
+ $this->themeProvider = $this->getMock(ThemeProviderInterface::class);
+ $this->object = (new ObjectManager($this))->getObject(MagentoImport::class, [
+ 'design' => $this->design,
+ 'fileSource' => $this->fileSource,
+ 'errorHandler' => $this->errorHandler,
+ 'assetRepo' => $this->assetRepo,
+ ]);
+ $objectReflection = new \ReflectionProperty(MagentoImport::class, 'themeProvider');
+ $objectReflection->setAccessible(true);
+ $objectReflection->setValue($this->object, $this->themeProvider);
}
/**
@@ -88,7 +97,7 @@ public function testProcess($originalContent, $foundPath, $resolvedPath, $foundF
->will($this->returnValue($relatedAsset));
$relatedAsset->expects($this->once())->method('getContext')->will($this->returnValue($context));
$theme = $this->getMockForAbstractClass('\Magento\Framework\View\Design\ThemeInterface');
- $this->themeList->expects($this->once())->method('getThemeByFullPath')->will($this->returnValue($theme));
+ $this->themeProvider->expects($this->once())->method('getThemeByFullPath')->will($this->returnValue($theme));
$files = [];
foreach ($foundFiles as $file) {
$fileObject = $this->getMock('Magento\Framework\View\File', [], [], '', false);
diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
index c6a54690734a0..40884c83bbaca 100644
--- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
+++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php
@@ -22,6 +22,7 @@
use Magento\Framework\Phrase;
use Magento\Framework\Stdlib\DateTime;
use Magento\Framework\Stdlib\StringUtils;
+use Magento\Framework\DB\Query\Generator as QueryGenerator;
/**
* @SuppressWarnings(PHPMD.ExcessivePublicCount)
@@ -183,6 +184,11 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
*/
protected $logger;
+ /**
+ * @var QueryGenerator
+ */
+ protected $queryGenerator;
+
/**
* @param \Magento\Framework\Stdlib\StringUtils|String $string
* @param DateTime $dateTime
@@ -3329,57 +3335,32 @@ public function insertFromSelect(Select $select, $table, array $fields = [], $mo
* @param int $stepCount
* @return \Magento\Framework\DB\Select[]
* @throws LocalizedException
+ * @deprecated
*/
public function selectsByRange($rangeField, \Magento\Framework\DB\Select $select, $stepCount = 100)
{
- $fromSelect = $select->getPart(\Magento\Framework\DB\Select::FROM);
- if (empty($fromSelect)) {
- throw new LocalizedException(
- new \Magento\Framework\Phrase('Select object must have correct "FROM" part')
- );
- }
-
- $tableName = [];
- $correlationName = '';
- foreach ($fromSelect as $correlationName => $formPart) {
- if ($formPart['joinType'] == \Magento\Framework\DB\Select::FROM) {
- $tableName = $formPart['tableName'];
- break;
- }
- }
-
- $selectRange = $this->select()
- ->from(
- $tableName,
- [
- new \Zend_Db_Expr('MIN(' . $this->quoteIdentifier($rangeField) . ') AS min'),
- new \Zend_Db_Expr('MAX(' . $this->quoteIdentifier($rangeField) . ') AS max'),
- ]
- );
-
- $rangeResult = $this->fetchRow($selectRange);
- $min = $rangeResult['min'];
- $max = $rangeResult['max'];
-
+ $iterator = $this->getQueryGenerator()->generate($rangeField, $select, $stepCount);
$queries = [];
- while ($min <= $max) {
- $partialSelect = clone $select;
- $partialSelect->where(
- $this->quoteIdentifier($correlationName) . '.'
- . $this->quoteIdentifier($rangeField) . ' >= ?',
- $min
- )
- ->where(
- $this->quoteIdentifier($correlationName) . '.'
- . $this->quoteIdentifier($rangeField) . ' < ?',
- $min + $stepCount
- );
- $queries[] = $partialSelect;
- $min += $stepCount;
+ foreach ($iterator as $query) {
+ $queries[] = $query;
}
return $queries;
}
+ /**
+ * Get query generator
+ *
+ * @return QueryGenerator
+ * @deprecated
+ */
+ private function getQueryGenerator()
+ {
+ if ($this->queryGenerator === null) {
+ $this->queryGenerator = \Magento\Framework\App\ObjectManager::getInstance()->create(QueryGenerator::class);
+ }
+ return $this->queryGenerator;
+ }
+
/**
* Get update table query using select object for join and update
*
diff --git a/lib/internal/Magento/Framework/DB/Query/BatchIterator.php b/lib/internal/Magento/Framework/DB/Query/BatchIterator.php
new file mode 100644
index 0000000000000..cf5e88c1b9944
--- /dev/null
+++ b/lib/internal/Magento/Framework/DB/Query/BatchIterator.php
@@ -0,0 +1,192 @@
+batchSize = $batchSize;
+ $this->select = $select;
+ $this->correlationName = $correlationName;
+ $this->rangeField = $rangeField;
+ $this->rangeFieldAlias = $rangeFieldAlias;
+ $this->connection = $select->getConnection();
+ }
+
+ /**
+ * @return Select
+ */
+ public function current()
+ {
+ if (null == $this->currentSelect) {
+ $this->currentSelect = $this->initSelectObject();
+ $itemsCount = $this->calculateBatchSize($this->currentSelect);
+ $this->isValid = $itemsCount > 0;
+ }
+ return $this->currentSelect;
+ }
+
+ /**
+ * @return Select
+ */
+ public function next()
+ {
+ if (null == $this->currentSelect) {
+ $this->current();
+ }
+ $select = $this->initSelectObject();
+ $itemsCountInSelect = $this->calculateBatchSize($select);
+ $this->isValid = $itemsCountInSelect > 0;
+ if ($this->isValid) {
+ $this->iteration++;
+ $this->currentSelect = $select;
+ } else {
+ $this->currentSelect = null;
+ }
+ return $this->currentSelect;
+ }
+
+ /**
+ * @return int
+ */
+ public function key()
+ {
+ return $this->iteration;
+ }
+
+ /**
+ * @return bool
+ */
+ public function valid()
+ {
+ return $this->isValid;
+ }
+
+ /**
+ * @return void
+ */
+ public function rewind()
+ {
+ $this->minValue = 0;
+ $this->currentSelect = null;
+ $this->iteration = 0;
+ $this->isValid = true;
+ }
+
+ /**
+ * Calculate batch size for select.
+ *
+ * @param Select $select
+ * @return int
+ */
+ private function calculateBatchSize(Select $select)
+ {
+ $wrapperSelect = $this->connection->select();
+ $wrapperSelect->from(
+ $select,
+ [
+ new \Zend_Db_Expr('MAX(' . $this->rangeFieldAlias . ') as max'),
+ new \Zend_Db_Expr('COUNT(*) as cnt')
+ ]
+ );
+ $row = $this->connection->fetchRow($wrapperSelect);
+ $this->minValue = $row['max'];
+ return intval($row['cnt']);
+ }
+
+ /**
+ * Initialize select object.
+ *
+ * @return \Magento\Framework\DB\Select
+ */
+ private function initSelectObject()
+ {
+ $object = clone $this->select;
+ $object->where(
+ $this->connection->quoteIdentifier($this->correlationName)
+ . '.' . $this->connection->quoteIdentifier($this->rangeField)
+ . ' > ?',
+ $this->minValue
+ );
+ $object->limit($this->batchSize);
+ /**
+ * Reset sort order section from origin select object
+ */
+ $object->order($this->correlationName . '.' . $this->rangeField . ' ' . \Magento\Framework\DB\Select::SQL_ASC);
+ return $object;
+ }
+}
diff --git a/lib/internal/Magento/Framework/DB/Query/BatchIteratorFactory.php b/lib/internal/Magento/Framework/DB/Query/BatchIteratorFactory.php
new file mode 100644
index 0000000000000..a51a650197def
--- /dev/null
+++ b/lib/internal/Magento/Framework/DB/Query/BatchIteratorFactory.php
@@ -0,0 +1,51 @@
+objectManager = $objectManager;
+ $this->instanceName = $instanceName;
+ }
+
+ /**
+ * Create class instance with specified parameters
+ *
+ * @param array $data
+ * @return \Magento\Framework\DB\Query\BatchIterator
+ */
+ public function create(array $data = [])
+ {
+ return $this->objectManager->create($this->instanceName, $data);
+ }
+}
diff --git a/lib/internal/Magento/Framework/DB/Query/Generator.php b/lib/internal/Magento/Framework/DB/Query/Generator.php
new file mode 100644
index 0000000000000..43f8388d3f449
--- /dev/null
+++ b/lib/internal/Magento/Framework/DB/Query/Generator.php
@@ -0,0 +1,79 @@
+iteratorFactory = $iteratorFactory;
+ }
+
+ /**
+ * Generate select query list with predefined items count in each select item.
+ *
+ * @param string $rangeField
+ * @param \Magento\Framework\DB\Select $select
+ * @param int $batchSize
+ * @return BatchIterator
+ * @throws LocalizedException
+ */
+ public function generate($rangeField, \Magento\Framework\DB\Select $select, $batchSize = 100)
+ {
+ $fromSelect = $select->getPart(\Magento\Framework\DB\Select::FROM);
+ if (empty($fromSelect)) {
+ throw new LocalizedException(
+ new \Magento\Framework\Phrase('Select object must have correct "FROM" part')
+ );
+ }
+
+ $fieldCorrelationName = '';
+ foreach ($fromSelect as $correlationName => $fromPart) {
+ if ($fromPart['joinType'] == \Magento\Framework\DB\Select::FROM) {
+ $fieldCorrelationName = $correlationName;
+ break;
+ }
+ }
+
+ $columns = $select->getPart(\Magento\Framework\DB\Select::COLUMNS);
+ /**
+ * Calculate $rangeField alias
+ */
+ $rangeFieldAlias = $rangeField;
+ foreach ($columns as $column) {
+ list($table, $columnName, $alias) = $column;
+ if ($table == $fieldCorrelationName && $columnName == $rangeField) {
+ $rangeFieldAlias = $alias ?: $rangeField;
+ break;
+ }
+ }
+
+ return $this->iteratorFactory->create(
+ [
+ 'select' => $select,
+ 'batchSize' => $batchSize,
+ 'correlationName' => $fieldCorrelationName,
+ 'rangeField' => $rangeField,
+ 'rangeFieldAlias' => $rangeFieldAlias
+ ]
+ );
+ }
+}
diff --git a/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php b/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php
index 748cfb4bef600..8359cd84a44c3 100644
--- a/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php
+++ b/lib/internal/Magento/Framework/DB/Test/Unit/Adapter/Pdo/MysqlTest.php
@@ -13,6 +13,7 @@
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\DB\Select;
+use Magento\Framework\DB\Query\Generator;
class MysqlTest extends \PHPUnit_Framework_TestCase
{
@@ -73,7 +74,8 @@ protected function setUp()
'_commit',
'_rollBack',
'query',
- 'fetchRow'
+ 'fetchRow',
+ 'getQueryGenerator'
],
[
'string' => $string,
@@ -441,73 +443,31 @@ public function testInsertOnDuplicateWithQuotedColumnName()
public function testSelectsByRange()
{
- $rangeField = 'test_id';
+ $queryGenerator = $this->getMock(Generator::class, [], [], '', false, false);
+
+ $resourceProperty = new \ReflectionProperty(
+ get_class($this->_adapter),
+ 'queryGenerator'
+ );
+ $resourceProperty->setAccessible(true);
+ $resourceProperty->setValue($this->_adapter, $queryGenerator);
+
$tableName = 'test';
+ $field = 'test_id';
+ $select = $this->_adapter->select()->from($tableName); //min = 1; max 180; count: 120
- $this->_adapter->expects($this->once())
- ->method('fetchRow')
- ->with(
- $this->_adapter->select()
- ->from(
- $tableName,
- [
- new \Zend_Db_Expr('MIN(' . $this->_adapter->quoteIdentifier($rangeField) . ') AS min'),
- new \Zend_Db_Expr('MAX(' . $this->_adapter->quoteIdentifier($rangeField) . ') AS max'),
- ]
- )
- )
- ->will($this->returnValue(['min' => 1, 'max' => 200]));
- $this->_adapter->expects($this->any())
- ->method('quote')
- ->will(
- $this->returnCallback(
- function ($values) {
- if (!is_array($values)) {
- $values = [$values];
- }
- foreach ($values as &$value) {
- $value = "'" . $value . "'";
- }
- return implode(',', $values);
- }
- )
- );
+ $data = [
+ $this->_adapter->select()->from($tableName)->where($field . '> ?', 0)->limit(50), //will return 0 ...61
+ $this->_adapter->select()->from($tableName)->where($field . '> ?', 61)->limit(50), //will return 62 ...159
+ $this->_adapter->select()->from($tableName)->where($field . '> ?', 159)->limit(50), //will return 160 ...180
+ ];
- $expectedSelect = $this->_adapter->select()
- ->from($tableName);
-
- $result = $this->_adapter->selectsByRange($rangeField, $expectedSelect, 50);
- $this->assertCount(200/50, $result);
- $prepareField = $this->_adapter->quoteIdentifier($tableName)
- . '.' . $this->_adapter->quoteIdentifier($rangeField);
- $this->assertEquals(
- $this->_adapter->select()
- ->from($tableName)
- ->where($prepareField . ' >= ?', 1)
- ->where($prepareField . ' < ?', 51),
- $result[0]
- );
- $this->assertEquals(
- $this->_adapter->select()
- ->from($tableName)
- ->where($prepareField . ' >= ?', 51)
- ->where($prepareField . ' < ?', 101),
- $result[1]
- );
- $this->assertEquals(
- $this->_adapter->select()
- ->from($tableName)
- ->where($prepareField . ' >= ?', 101)
- ->where($prepareField . ' < ?', 151),
- $result[2]
- );
- $this->assertEquals(
- $this->_adapter->select()
- ->from($tableName)
- ->where($prepareField . ' >= ?', 151)
- ->where($prepareField . ' < ?', 201),
- $result[3]
- );
+ $queryGenerator->expects($this->once())
+ ->method('generate')
+ ->with($field, $select, 50)
+ ->willReturn($data);
+
+ $this->assertEquals($data, $this->_adapter->selectsByRange($field, $select, 50));
}
/**
diff --git a/lib/internal/Magento/Framework/Filesystem/Directory/Write.php b/lib/internal/Magento/Framework/Filesystem/Directory/Write.php
index 483434b1d8fc9..6dde49a65f0bc 100644
--- a/lib/internal/Magento/Framework/Filesystem/Directory/Write.php
+++ b/lib/internal/Magento/Framework/Filesystem/Directory/Write.php
@@ -143,8 +143,6 @@ public function copyFile($path, $destination, WriteInterface $targetDirectory =
*/
public function createSymlink($path, $destination, WriteInterface $targetDirectory = null)
{
- $this->assertIsFile($path);
-
$targetDirectory = $targetDirectory ?: $this;
$parentDirectory = $this->driver->getParentDirectory($destination);
if (!$targetDirectory->isExist($parentDirectory)) {
diff --git a/lib/internal/Magento/Framework/Filesystem/Directory/WriteInterface.php b/lib/internal/Magento/Framework/Filesystem/Directory/WriteInterface.php
index 472c54a08d202..3fa0513dd21a0 100644
--- a/lib/internal/Magento/Framework/Filesystem/Directory/WriteInterface.php
+++ b/lib/internal/Magento/Framework/Filesystem/Directory/WriteInterface.php
@@ -48,7 +48,7 @@ public function renameFile($path, $newPath, WriteInterface $targetDirectory = nu
public function copyFile($path, $destination, WriteInterface $targetDirectory = null);
/**
- * Creates symlink on a file and places it to destination
+ * Creates symlink on a file or directory and places it to destination
*
* @param string $path
* @param string $destination
diff --git a/lib/internal/Magento/Framework/Filesystem/Filter/ExcludeFilter.php b/lib/internal/Magento/Framework/Filesystem/Filter/ExcludeFilter.php
new file mode 100644
index 0000000000000..a00bf449718ab
--- /dev/null
+++ b/lib/internal/Magento/Framework/Filesystem/Filter/ExcludeFilter.php
@@ -0,0 +1,56 @@
+_filters = $filters;
+ }
+
+ /**
+ * Check whether the current element of the iterator is acceptable
+ *
+ * @return bool
+ */
+ public function accept()
+ {
+ $current = str_replace('\\', '/', $this->current()->__toString());
+ $currentFilename = str_replace('\\', '/', $this->current()->getFilename());
+
+ if ($currentFilename == '.' || $currentFilename == '..') {
+ return false;
+ }
+
+ foreach ($this->_filters as $filter) {
+ $filter = str_replace('\\', '/', $filter);
+ if (false !== strpos($current, $filter)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/lib/internal/Magento/Framework/Filesystem/Test/Unit/File/ExcludeFilterTest.php b/lib/internal/Magento/Framework/Filesystem/Test/Unit/File/ExcludeFilterTest.php
new file mode 100644
index 0000000000000..bca9b5b667685
--- /dev/null
+++ b/lib/internal/Magento/Framework/Filesystem/Test/Unit/File/ExcludeFilterTest.php
@@ -0,0 +1,57 @@
+iterator = $this->getFilesIterator();
+ }
+
+ public function testExclusion()
+ {
+ $iterator = new ExcludeFilter(
+ $this->iterator,
+ [
+ BP . '/var/session/'
+ ]
+ );
+
+ foreach ($iterator as $i) {
+ $result[] = $i;
+ }
+
+ $this->assertTrue(!in_array(BP . '/var/session/', $result), 'Filtered path should not be in array');
+ }
+
+ private function getFilesIterator ()
+ {
+ $files = [
+ BP . '/var/',
+ BP . '/var/session/',
+ BP . '/var/cache/'
+ ];
+
+ foreach ($files as $file) {
+ $item = $this->getMockBuilder('SplFileInfoClass')->setMethods(['__toString', 'getFilename'])->getMock();
+ $item->expects($this->any())->method('__toString')->willReturn($file);
+ $item->expects($this->any())->method('getFilename')->willReturn('notDots');
+ yield $item;
+ }
+ }
+}
diff --git a/lib/internal/Magento/Framework/Module/Dir/Reader.php b/lib/internal/Magento/Framework/Module/Dir/Reader.php
index 7a8b1f11ef184..353f7e51c5906 100644
--- a/lib/internal/Magento/Framework/Module/Dir/Reader.php
+++ b/lib/internal/Magento/Framework/Module/Dir/Reader.php
@@ -46,6 +46,13 @@ class Reader
*/
protected $readFactory;
+ /**
+ * Found configuration files grouped by configuration types (filename).
+ *
+ * @var array
+ */
+ private $fileIterators = [];
+
/**
* @param Dir $moduleDirs
* @param ModuleListInterface $moduleList
@@ -65,24 +72,42 @@ public function __construct(
}
/**
- * Go through all modules and find configuration files of active modules
+ * Go through all modules and find configuration files of active modules.
*
* @param string $filename
* @return FileIterator
*/
public function getConfigurationFiles($filename)
{
- return $this->fileIteratorFactory->create($this->getFiles($filename, Dir::MODULE_ETC_DIR));
+ return $this->getFilesIterator($filename, Dir::MODULE_ETC_DIR);
}
/**
- * Go through all modules and find composer.json files of active modules
+ * Go through all modules and find composer.json files of active modules.
*
* @return FileIterator
*/
public function getComposerJsonFiles()
{
- return $this->fileIteratorFactory->create($this->getFiles('composer.json'));
+ return $this->getFilesIterator('composer.json');
+ }
+
+ /**
+ * Retrieve iterator for files with $filename from components located in component $subDir.
+ *
+ * @param string $filename
+ * @param string $subDir
+ *
+ * @return FileIterator
+ */
+ private function getFilesIterator($filename, $subDir = '')
+ {
+ if (!isset($this->fileIterators[$subDir][$filename])) {
+ $this->fileIterators[$subDir][$filename] = $this->fileIteratorFactory->create(
+ $this->getFiles($filename, $subDir)
+ );
+ }
+ return $this->fileIterators[$subDir][$filename];
}
/**
@@ -96,9 +121,9 @@ private function getFiles($filename, $subDir = '')
{
$result = [];
foreach ($this->modulesList->getNames() as $moduleName) {
- $moduleEtcDir = $this->getModuleDir($subDir, $moduleName);
- $file = $moduleEtcDir . '/' . $filename;
- $directoryRead = $this->readFactory->create($moduleEtcDir);
+ $moduleSubDir = $this->getModuleDir($subDir, $moduleName);
+ $file = $moduleSubDir . '/' . $filename;
+ $directoryRead = $this->readFactory->create($moduleSubDir);
$path = $directoryRead->getRelativePath($file);
if ($directoryRead->isExist($path)) {
$result[] = $file;
@@ -159,5 +184,6 @@ public function getModuleDir($type, $moduleName)
public function setModuleDir($moduleName, $type, $path)
{
$this->customModuleDirs[$moduleName][$type] = $path;
+ $this->fileIterators = [];
}
}
diff --git a/lib/internal/Magento/Framework/Test/Unit/App/ResourceConnectionTest.php b/lib/internal/Magento/Framework/Test/Unit/App/ResourceConnectionTest.php
new file mode 100644
index 0000000000000..064faa7936964
--- /dev/null
+++ b/lib/internal/Magento/Framework/Test/Unit/App/ResourceConnectionTest.php
@@ -0,0 +1,102 @@
+deploymentConfigMock = $this->getMockBuilder(DeploymentConfig::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connectionFactoryMock = $this->getMockBuilder(ConnectionFactoryInterface::class)
+ ->getMock();
+
+ $this->configMock = $this->getMockBuilder(ConfigInterface::class)->getMock();
+
+ $this->objectManager = (new ObjectManager($this));
+ $this->unit = $this->objectManager->getObject(
+ ResourceConnection::class,
+ [
+ 'deploymentConfig' => $this->deploymentConfigMock,
+ 'connectionFactory' => $this->connectionFactoryMock,
+ 'resourceConfig' => $this->configMock,
+ ]
+ );
+ }
+
+ public function testGetConnectionByName()
+ {
+ $this->deploymentConfigMock->expects(self::once())->method('get')
+ ->with(ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTIONS . '/default')
+ ->willReturn(['config']);
+ $this->connectionFactoryMock->expects(self::once())->method('create')
+ ->with(['config'])
+ ->willReturn('connection');
+
+ self::assertEquals('connection', $this->unit->getConnectionByName('default'));
+ }
+
+ public function testGetExistingConnectionByName()
+ {
+ $unit = $this->objectManager->getObject(
+ ResourceConnection::class,
+ [
+ 'deploymentConfig' => $this->deploymentConfigMock,
+ ]
+ );
+ $connectionProperty = new \ReflectionProperty(
+ ResourceConnection::class,
+ 'connections'
+ );
+ $connectionProperty->setAccessible(true);
+ $connectionProperty->setValue($unit, ['default_process_' . getmypid() => 'existing_connection']);
+ $this->deploymentConfigMock->expects(self::never())->method('get');
+
+ self::assertEquals('existing_connection', $unit->getConnectionByName('default'));
+ }
+
+ public function testCloseConnection()
+ {
+ $this->configMock->expects(self::once())->method('getConnectionName')->with('default');
+
+ $this->unit->closeConnection('default');
+
+ }
+}
diff --git a/lib/internal/Magento/Framework/Test/Unit/DB/Query/BatchIteratorTest.php b/lib/internal/Magento/Framework/Test/Unit/DB/Query/BatchIteratorTest.php
new file mode 100644
index 0000000000000..e522daf97a802
--- /dev/null
+++ b/lib/internal/Magento/Framework/Test/Unit/DB/Query/BatchIteratorTest.php
@@ -0,0 +1,200 @@
+batchSize = 10;
+ $this->correlationName = 'correlationName';
+ $this->rangeField = 'rangeField';
+ $this->rangeFieldAlias = 'rangeFieldAlias';
+
+ $this->selectMock = $this->getMock(Select::class, [], [], '', false, false);
+ $this->wrapperSelectMock = $this->getMock(Select::class, [], [], '', false, false);
+ $this->connectionMock = $this->getMock(AdapterInterface::class);
+ $this->connectionMock->expects($this->any())->method('select')->willReturn($this->wrapperSelectMock);
+ $this->selectMock->expects($this->once())->method('getConnection')->willReturn($this->connectionMock);
+ $this->connectionMock->expects($this->any())->method('quoteIdentifier')->willReturnArgument(0);
+
+ $this->model = new BatchIterator(
+ $this->selectMock,
+ $this->batchSize,
+ $this->correlationName,
+ $this->rangeField,
+ $this->rangeFieldAlias
+ );
+ }
+
+ /**
+ * Test steps:
+ * 1. $iterator->current();
+ * 2. $iterator->current();
+ * 3. $iterator->key();
+ * @return void
+ */
+ public function testCurrent()
+ {
+ $filed = $this->correlationName . '.' . $this->rangeField;
+
+ $this->selectMock->expects($this->once())->method('where')->with($filed . ' > ?', 0);
+ $this->selectMock->expects($this->once())->method('limit')->with($this->batchSize);
+ $this->selectMock->expects($this->once())->method('order')->with($filed . ' ASC');
+ $this->assertEquals($this->selectMock, $this->model->current());
+ $this->assertEquals($this->selectMock, $this->model->current());
+ $this->assertEquals(0, $this->model->key());
+ }
+
+ /**
+ * SQL: select * from users
+ * Batch size: 10
+ * IDS: [1 - 25]
+ * Items count: 25
+ * Expected batches: [1-10, 11-20, 20-25]
+ *
+ * Test steps:
+ * 1. $iterator->rewind();
+ * 2. $iterator->valid();
+ * 3. $iterator->current();
+ * 4. $iterator->key();
+ *
+ * 1. $iterator->next()
+ * 2. $iterator->valid();
+ * 3. $iterator->current();
+ * 4. $iterator->key();
+ *
+ * 1. $iterator->next()
+ * 2. $iterator->valid();
+ * 3. $iterator->current();
+ * 4. $iterator->key();
+ *
+ *
+ * 1. $iterator->next()
+ * 2. $iterator->valid();
+ * @return void
+ */
+ public function testIterations()
+ {
+ $startCallIndex = 3;
+ $stepCall = 4;
+
+ $this->connectionMock->expects($this->at($startCallIndex))
+ ->method('fetchRow')
+ ->willReturn(['max' => 10, 'cnt' => 10]);
+
+ $this->connectionMock->expects($this->at($startCallIndex += $stepCall))
+ ->method('fetchRow')
+ ->willReturn(['max' => 20, 'cnt' => 10]);
+
+ $this->connectionMock->expects($this->at($startCallIndex += $stepCall))
+ ->method('fetchRow')
+ ->willReturn(['max' => 25, 'cnt' => 5]);
+
+ $this->connectionMock->expects($this->at($startCallIndex += $stepCall))
+ ->method('fetchRow')
+ ->willReturn(['max' => null, 'cnt' => 0]);
+
+ /**
+ * Test 3 iterations
+ * [1-10, 11-20, 20-25]
+ */
+ $iteration = 0;
+ $result = [];
+ foreach ($this->model as $key => $select) {
+ $result[] = $select;
+ $this->assertEquals($iteration, $key);
+ $iteration++;
+ }
+ $this->assertCount(3, $result);
+ }
+
+ /**
+ * Test steps:
+ * 1. $iterator->next();
+ * 2. $iterator->key()
+ * 3. $iterator->next();
+ * 4. $iterator->current()
+ * 5. $iterator->key()
+ * @return void
+ */
+ public function testNext()
+ {
+ $filed = $this->correlationName . '.' . $this->rangeField;
+ $this->selectMock->expects($this->at(0))->method('where')->with($filed . ' > ?', 0);
+ $this->selectMock->expects($this->exactly(3))->method('limit')->with($this->batchSize);
+ $this->selectMock->expects($this->exactly(3))->method('order')->with($filed . ' ASC');
+ $this->selectMock->expects($this->at(3))->method('where')->with($filed . ' > ?', 25);
+
+ $this->wrapperSelectMock->expects($this->exactly(3))->method('from')->with(
+ $this->selectMock,
+ [
+ new \Zend_Db_Expr('MAX(' . $this->rangeFieldAlias . ') as max'),
+ new \Zend_Db_Expr('COUNT(*) as cnt')
+ ]
+ );
+ $this->connectionMock->expects($this->exactly(3))
+ ->method('fetchRow')
+ ->with($this->wrapperSelectMock)
+ ->willReturn(['max' => 25, 'cnt' => 10]);
+
+ $this->assertEquals($this->selectMock, $this->model->next());
+ $this->assertEquals(1, $this->model->key());
+
+ $this->assertEquals($this->selectMock, $this->model->next());
+ $this->assertEquals($this->selectMock, $this->model->current());
+ $this->assertEquals(2, $this->model->key());
+ }
+}
diff --git a/lib/internal/Magento/Framework/Test/Unit/DB/Query/GeneratorTest.php b/lib/internal/Magento/Framework/Test/Unit/DB/Query/GeneratorTest.php
new file mode 100644
index 0000000000000..4be22eb14ca85
--- /dev/null
+++ b/lib/internal/Magento/Framework/Test/Unit/DB/Query/GeneratorTest.php
@@ -0,0 +1,168 @@
+factoryMock = $this->getMock(BatchIteratorFactory::class, [], [], '', false, false);
+ $this->selectMock = $this->getMock(Select::class, [], [], '', false, false);
+ $this->iteratorMock = $this->getMock(BatchIterator::class, [], [], '', false, false);
+ $this->model = new Generator($this->factoryMock);
+ }
+
+ /**
+ * Test success generate.
+ * @return void
+ */
+ public function testGenerate()
+ {
+ $map = [
+ [
+ Select::FROM,
+ [
+ 'cp' => ['joinType' => Select::FROM]
+ ]
+ ],
+ [
+ Select::COLUMNS,
+ [
+ ['cp', 'entity_id', 'product_id']
+ ]
+ ]
+ ];
+ $this->selectMock->expects($this->exactly(2))->method('getPart')->willReturnMap($map);
+ $this->factoryMock->expects($this->once())->method('create')->with(
+ [
+ 'select' => $this->selectMock,
+ 'batchSize' => 100,
+ 'correlationName' => 'cp',
+ 'rangeField' => 'entity_id',
+ 'rangeFieldAlias' => 'product_id'
+ ]
+ )->willReturn($this->iteratorMock);
+ $this->assertEquals($this->iteratorMock, $this->model->generate('entity_id', $this->selectMock, 100));
+ }
+
+ /**
+ * Test batch generation with invalid select object.
+ *
+ * @expectedException \Magento\Framework\Exception\LocalizedException
+ * @expectedExceptionMessage Select object must have correct "FROM" part
+ * @return void
+ */
+ public function testGenerateWithoutFromPart()
+ {
+ $map = [
+ [Select::FROM, []],
+ [
+ Select::COLUMNS,
+ [
+ ['cp', 'entity_id', 'product_id']
+ ]
+ ]
+ ];
+ $this->selectMock->expects($this->any())->method('getPart')->willReturnMap($map);
+ $this->factoryMock->expects($this->never())->method('create');
+ $this->model->generate('entity_id', $this->selectMock, 100);
+ }
+
+ /**
+ * Test generate batches with rangeField without alias.
+ * @return void
+ */
+ public function testGenerateWithRangeFieldWithoutAlias()
+ {
+ $map = [
+ [
+ Select::FROM,
+ [
+ 'cp' => ['joinType' => Select::FROM]
+ ]
+ ],
+ [
+ Select::COLUMNS,
+ [
+ ['cp', 'entity_id', null]
+ ]
+ ]
+ ];
+ $this->selectMock->expects($this->exactly(2))->method('getPart')->willReturnMap($map);
+ $this->factoryMock->expects($this->once())->method('create')->with(
+ [
+ 'select' => $this->selectMock,
+ 'batchSize' => 100,
+ 'correlationName' => 'cp',
+ 'rangeField' => 'entity_id',
+ 'rangeFieldAlias' => 'entity_id'
+ ]
+ )->willReturn($this->iteratorMock);
+ $this->assertEquals($this->iteratorMock, $this->model->generate('entity_id', $this->selectMock, 100));
+ }
+
+ /**
+ * Test generate batches with wild-card.
+ *
+ * @return void
+ */
+ public function testGenerateWithInvalidWithWildcard()
+ {
+ $map = [
+ [
+ Select::FROM,
+ [
+ 'cp' => ['joinType' => Select::FROM]
+ ]
+ ],
+ [
+ Select::COLUMNS,
+ [
+ ['cp', '*', null]
+ ]
+ ]
+ ];
+ $this->selectMock->expects($this->exactly(2))->method('getPart')->willReturnMap($map);
+ $this->factoryMock->expects($this->once())->method('create')->with(
+ [
+ 'select' => $this->selectMock,
+ 'batchSize' => 100,
+ 'correlationName' => 'cp',
+ 'rangeField' => 'entity_id',
+ 'rangeFieldAlias' => 'entity_id'
+ ]
+ )->willReturn($this->iteratorMock);
+ $this->assertEquals($this->iteratorMock, $this->model->generate('entity_id', $this->selectMock, 100));
+ }
+}
diff --git a/lib/internal/Magento/Framework/Test/Unit/TranslateTest.php b/lib/internal/Magento/Framework/Test/Unit/TranslateTest.php
index 7f06f5ee95917..aa1eaa3b1f7c5 100644
--- a/lib/internal/Magento/Framework/Test/Unit/TranslateTest.php
+++ b/lib/internal/Magento/Framework/Test/Unit/TranslateTest.php
@@ -170,8 +170,9 @@ public function testLoadData($area, $forceReload, $cachedData)
];
$this->resource->expects($this->any())->method('getTranslationArray')->will($this->returnValue($dbData));
- $this->cache->expects($this->exactly(1))
- ->method('save');
+ if (!$forceReload) {
+ $this->cache->expects($this->exactly(1))->method('save');
+ }
$this->translate->loadData($area, $forceReload);
diff --git a/lib/internal/Magento/Framework/Translate.php b/lib/internal/Magento/Framework/Translate.php
index 0b10a4151f459..5d3cf722761df 100644
--- a/lib/internal/Magento/Framework/Translate.php
+++ b/lib/internal/Magento/Framework/Translate.php
@@ -181,7 +181,9 @@ public function loadData($area = null, $forceReload = false)
$this->_loadPackTranslation();
$this->_loadDbTranslation();
- $this->_saveCache();
+ if (!$forceReload) {
+ $this->_saveCache();
+ }
return $this;
}
diff --git a/lib/internal/Magento/Framework/View/Asset/Bundle.php b/lib/internal/Magento/Framework/View/Asset/Bundle.php
index 002382c6a0e70..2f0c101f88e6a 100644
--- a/lib/internal/Magento/Framework/View/Asset/Bundle.php
+++ b/lib/internal/Magento/Framework/View/Asset/Bundle.php
@@ -26,7 +26,7 @@ class Bundle
*/
protected $assetsContent = [];
- /** @var Bundle\Config */
+ /** @var Bundle\ConfigInterface */
protected $bundleConfig;
/**
@@ -261,6 +261,7 @@ protected function save($types)
$assetsParts = reset($parts);
$context = reset($assetsParts['assets'])->getContext();
$bundlePath = empty($bundlePath) ? $context->getPath() . Manager::BUNDLE_PATH : $bundlePath;
+ $dir->delete($context->getPath() . DIRECTORY_SEPARATOR . Manager::BUNDLE_JS_DIR);
$this->fillContent($parts, $context);
}
diff --git a/lib/internal/Magento/Framework/View/Asset/Bundle/Config.php b/lib/internal/Magento/Framework/View/Asset/Bundle/Config.php
index 21e974fca57e0..ebd0a210052ce 100644
--- a/lib/internal/Magento/Framework/View/Asset/Bundle/Config.php
+++ b/lib/internal/Magento/Framework/View/Asset/Bundle/Config.php
@@ -6,10 +6,12 @@
namespace Magento\Framework\View\Asset\Bundle;
+use Magento\Framework\App\ObjectManager;
use Magento\Framework\View;
use Magento\Framework\View\Asset\Bundle;
use Magento\Framework\View\Design\Theme\ListInterface;
use Magento\Framework\View\Asset\File\FallbackContext;
+use Magento\Framework\View\Design\Theme\ThemeProviderInterface;
class Config implements Bundle\ConfigInterface
{
@@ -30,6 +32,16 @@ class Config implements Bundle\ConfigInterface
*/
protected $viewConfig;
+ /**
+ * @var ThemeProviderInterface
+ */
+ private $themeProvider;
+
+ /**
+ * @var \Magento\Framework\Config\View[]
+ */
+ private $config = [];
+
/**
* @param View\ConfigInterface $viewConfig
* @param ListInterface $themeList
@@ -57,12 +69,17 @@ public function isSplit(FallbackContext $assetContext)
*/
public function getConfig(FallbackContext $assetContext)
{
- return $this->viewConfig->getViewConfig([
- 'area' => $assetContext->getAreaCode(),
- 'themeModel' => $this->themeList->getThemeByFullPath(
- $assetContext->getAreaCode() . '/' . $assetContext->getThemePath()
- )
- ]);
+ $themePath = $assetContext->getAreaCode() . '/' . $assetContext->getThemePath();
+ if (!isset($this->config[$themePath])) {
+ $this->config[$themePath] = $this->viewConfig->getViewConfig([
+ 'area' => $assetContext->getAreaCode(),
+ 'themeModel' => $this->getThemeProvider()->getThemeByFullPath(
+ $themePath
+ )
+ ]);
+ }
+
+ return $this->config[$themePath];
}
/**
@@ -83,7 +100,20 @@ public function getPartSize(FallbackContext $assetContext)
case 'MB':
return (int)$size * 1024;
default:
- return (int)$size / 1024;
+ return (int)($size / 1024);
}
}
+
+ /**
+ * @return ThemeProviderInterface
+ * @deprecated
+ */
+ private function getThemeProvider()
+ {
+ if (null === $this->themeProvider) {
+ $this->themeProvider = ObjectManager::getInstance()->get(ThemeProviderInterface::class);
+ }
+
+ return $this->themeProvider;
+ }
}
diff --git a/lib/internal/Magento/Framework/View/Asset/Bundle/Manager.php b/lib/internal/Magento/Framework/View/Asset/Bundle/Manager.php
index 2e09ea6ca92c7..0b072eddf08ce 100644
--- a/lib/internal/Magento/Framework/View/Asset/Bundle/Manager.php
+++ b/lib/internal/Magento/Framework/View/Asset/Bundle/Manager.php
@@ -18,6 +18,8 @@
*/
class Manager
{
+ const BUNDLE_JS_DIR = 'js/bundle';
+
const BUNDLE_PATH = '/js/bundle/bundle';
const ASSET_TYPE_JS = 'js';
@@ -41,6 +43,7 @@ class Manager
/** @var array */
public static $availableTypes = [self::ASSET_TYPE_JS, self::ASSET_TYPE_HTML];
+
/**
* @var Asset\Minification
*/
@@ -127,7 +130,7 @@ protected function isExcludedFile($filePath, $asset)
/** @var $asset LocalInterface */
$filePathInfo = $this->splitPath($filePath);
if ($filePathInfo && $this->compareModules($filePathInfo, $asset)) {
- return $asset->getSourceFile() == $filePathInfo['excludedPath'];
+ return $asset->getFilePath() == $filePathInfo['excludedPath'];
}
return false;
}
@@ -176,7 +179,7 @@ protected function splitPath($path)
*/
public function addAsset(LocalInterface $asset)
{
- if (!($this->isValidAsset($asset))) {
+ if (!$this->isValidAsset($asset)) {
return false;
}
@@ -237,14 +240,9 @@ protected function isValidType(LocalInterface $asset)
return false;
}
- if ($type == self::ASSET_TYPE_HTML) {
- return $asset->getModule() !== '';
- }
-
return true;
}
-
/**
* Flush bundle
*
diff --git a/lib/internal/Magento/Framework/View/Asset/LockerProcess.php b/lib/internal/Magento/Framework/View/Asset/LockerProcess.php
index 01b186ac67772..e8938211fecbf 100644
--- a/lib/internal/Magento/Framework/View/Asset/LockerProcess.php
+++ b/lib/internal/Magento/Framework/View/Asset/LockerProcess.php
@@ -9,6 +9,8 @@
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\FileSystemException;
use Magento\Framework\Filesystem\Directory\WriteInterface;
+use Magento\Framework\App\State;
+use Magento\Framework\App\ObjectManager;
/**
* Class LockerProcess
@@ -40,6 +42,11 @@ class LockerProcess implements LockerProcessInterface
*/
private $tmpDirectory;
+ /**
+ * @var State
+ */
+ private $state;
+
/**
* Constructor
*
@@ -52,19 +59,21 @@ public function __construct(Filesystem $filesystem)
/**
* @inheritdoc
- * @throws FileSystemException
*/
public function lockProcess($lockName)
{
+ if ($this->getState()->getMode() == State::MODE_PRODUCTION) {
+ return;
+ }
+
$this->tmpDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
$this->lockFilePath = $this->getFilePath($lockName);
while ($this->isProcessLocked()) {
- sleep(1);
+ usleep(1000);
}
$this->tmpDirectory->writeFile($this->lockFilePath, time());
-
}
/**
@@ -73,6 +82,10 @@ public function lockProcess($lockName)
*/
public function unlockProcess()
{
+ if ($this->getState()->getMode() == State::MODE_PRODUCTION) {
+ return ;
+ }
+
$this->tmpDirectory->delete($this->lockFilePath);
}
@@ -80,14 +93,18 @@ public function unlockProcess()
* Check whether generation process has already locked
*
* @return bool
- * @throws FileSystemException
*/
private function isProcessLocked()
{
if ($this->tmpDirectory->isExist($this->lockFilePath)) {
- $lockTime = (int) $this->tmpDirectory->readFile($this->lockFilePath);
- if ((time() - $lockTime) >= self::MAX_LOCK_TIME) {
- $this->tmpDirectory->delete($this->lockFilePath);
+ try {
+ $lockTime = (int)$this->tmpDirectory->readFile($this->lockFilePath);
+ if ((time() - $lockTime) >= self::MAX_LOCK_TIME) {
+ $this->tmpDirectory->delete($this->lockFilePath);
+
+ return false;
+ }
+ } catch (FileSystemException $e) {
return false;
}
@@ -108,4 +125,16 @@ private function getFilePath($name)
{
return DirectoryList::TMP . DIRECTORY_SEPARATOR . $name . self::LOCK_EXTENSION;
}
+
+ /**
+ * @return State
+ * @deprecated
+ */
+ private function getState()
+ {
+ if (null === $this->state) {
+ $this->state = ObjectManager::getInstance()->get(State::class);
+ }
+ return $this->state;
+ }
}
diff --git a/lib/internal/Magento/Framework/View/Asset/Minification.php b/lib/internal/Magento/Framework/View/Asset/Minification.php
index 255c9690e3fa9..1e32e32b99676 100644
--- a/lib/internal/Magento/Framework/View/Asset/Minification.php
+++ b/lib/internal/Magento/Framework/View/Asset/Minification.php
@@ -21,18 +21,21 @@ class Minification
* @var ScopeConfigInterface
*/
private $scopeConfig;
+
/**
* @var State
*/
private $appState;
+
/**
* @var string
*/
private $scope;
+
/**
* @var array
*/
- private $excludes = [];
+ private $configCache = [];
/**
* @param ScopeConfigInterface $scopeConfig
@@ -54,12 +57,16 @@ public function __construct(ScopeConfigInterface $scopeConfig, State $appState,
*/
public function isEnabled($contentType)
{
- return
- $this->appState->getMode() != State::MODE_DEVELOPER &&
- (bool)$this->scopeConfig->isSetFlag(
- sprintf(self::XML_PATH_MINIFICATION_ENABLED, $contentType),
- $this->scope
- );
+ if (!isset($this->configCache[self::XML_PATH_MINIFICATION_ENABLED][$contentType])) {
+ $this->configCache[self::XML_PATH_MINIFICATION_ENABLED][$contentType] =
+ $this->appState->getMode() != State::MODE_DEVELOPER &&
+ (bool)$this->scopeConfig->isSetFlag(
+ sprintf(self::XML_PATH_MINIFICATION_ENABLED, $contentType),
+ $this->scope
+ );
+ }
+
+ return $this->configCache[self::XML_PATH_MINIFICATION_ENABLED][$contentType];
}
/**
@@ -131,15 +138,15 @@ public function isExcluded($filename)
*/
public function getExcludes($contentType)
{
- if (!isset($this->excludes[$contentType])) {
- $this->excludes[$contentType] = [];
+ if (!isset($this->configCache[self::XML_PATH_MINIFICATION_EXCLUDES][$contentType])) {
+ $this->configCache[self::XML_PATH_MINIFICATION_EXCLUDES][$contentType] = [];
$key = sprintf(self::XML_PATH_MINIFICATION_EXCLUDES, $contentType);
foreach (explode("\n", $this->scopeConfig->getValue($key, $this->scope)) as $exclude) {
if (trim($exclude) != '') {
- $this->excludes[$contentType][] = trim($exclude);
+ $this->configCache[self::XML_PATH_MINIFICATION_EXCLUDES][$contentType][] = trim($exclude);
}
};
}
- return $this->excludes[$contentType];
+ return $this->configCache[self::XML_PATH_MINIFICATION_EXCLUDES][$contentType];
}
}
diff --git a/lib/internal/Magento/Framework/View/Asset/Repository.php b/lib/internal/Magento/Framework/View/Asset/Repository.php
index c4171b153e089..e75a728610c5a 100644
--- a/lib/internal/Magento/Framework/View/Asset/Repository.php
+++ b/lib/internal/Magento/Framework/View/Asset/Repository.php
@@ -8,7 +8,8 @@
use Magento\Framework\UrlInterface;
use Magento\Framework\App\Filesystem\DirectoryList;
-use Magento\Framework\Filesystem;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\View\Design\Theme\ThemeProviderInterface;
/**
* A repository service for view assets
@@ -33,6 +34,7 @@ class Repository
/**
* @var \Magento\Framework\View\Design\Theme\ListInterface
+ * @deprecated
*/
private $themeList;
@@ -70,11 +72,17 @@ class Repository
* @var File\ContextFactory
*/
private $contextFactory;
+
/**
* @var RemoteFactory
*/
private $remoteFactory;
+ /**
+ * @var ThemeProviderInterface
+ */
+ private $themeProvider;
+
/**
* @param \Magento\Framework\UrlInterface $baseUrl
* @param \Magento\Framework\View\DesignInterface $design
@@ -136,7 +144,7 @@ public function updateDesignParams(array &$params)
}
if ($theme) {
- $params['themeModel'] = $this->themeList->getThemeByFullPath($area . '/' . $theme);
+ $params['themeModel'] = $this->getThemeProvider()->getThemeByFullPath($area . '/' . $theme);
if (!$params['themeModel']) {
throw new \UnexpectedValueException("Could not find theme '$theme' for area '$area'");
}
@@ -156,6 +164,19 @@ public function updateDesignParams(array &$params)
return $this;
}
+ /**
+ * @return ThemeProviderInterface
+ * @deprecated
+ */
+ private function getThemeProvider()
+ {
+ if (null === $this->themeProvider) {
+ $this->themeProvider = ObjectManager::getInstance()->get(ThemeProviderInterface::class);
+ }
+
+ return $this->themeProvider;
+ }
+
/**
* Get default design parameter
*
diff --git a/lib/internal/Magento/Framework/View/Asset/Source.php b/lib/internal/Magento/Framework/View/Asset/Source.php
index fa27473c1343b..b70c423364a6d 100644
--- a/lib/internal/Magento/Framework/View/Asset/Source.php
+++ b/lib/internal/Magento/Framework/View/Asset/Source.php
@@ -9,6 +9,8 @@
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\View\Asset\PreProcessor\ChainFactoryInterface;
use Magento\Framework\View\Design\FileResolution\Fallback\Resolver\Simple;
+use Magento\Framework\View\Design\Theme\ThemeProviderInterface;
+use Magento\Framework\App\ObjectManager;
/**
* A service for preprocessing content of assets
@@ -44,9 +46,15 @@ class Source
/**
* @var \Magento\Framework\View\Design\Theme\ListInterface
+ * @deprecated
*/
private $themeList;
+ /**
+ * @var ThemeProviderInterface
+ */
+ private $themeProvider;
+
/**
* @var ChainFactoryInterface
*/
@@ -189,7 +197,9 @@ private function findFileThroughFallback(
LocalInterface $asset,
\Magento\Framework\View\Asset\File\FallbackContext $context
) {
- $themeModel = $this->themeList->getThemeByFullPath($context->getAreaCode() . '/' . $context->getThemePath());
+ $themeModel = $this->getThemeProvider()->getThemeByFullPath(
+ $context->getAreaCode() . '/' . $context->getThemePath()
+ );
$sourceFile = $this->fallback->getFile(
$context->getAreaCode(),
$themeModel,
@@ -200,6 +210,19 @@ private function findFileThroughFallback(
return $sourceFile;
}
+ /**
+ * @return ThemeProviderInterface
+ * @deprecated
+ */
+ private function getThemeProvider()
+ {
+ if (null === $this->themeProvider) {
+ $this->themeProvider = ObjectManager::getInstance()->get(ThemeProviderInterface::class);
+ }
+
+ return $this->themeProvider;
+ }
+
/**
* Find asset file by simply appending its path to the directory in context
*
diff --git a/lib/internal/Magento/Framework/View/Config.php b/lib/internal/Magento/Framework/View/Config.php
index c8960cb37845e..b72fe87c4acc4 100644
--- a/lib/internal/Magento/Framework/View/Config.php
+++ b/lib/internal/Magento/Framework/View/Config.php
@@ -57,16 +57,25 @@ public function __construct(
public function getViewConfig(array $params = [])
{
$this->assetRepo->updateDesignParams($params);
- /** @var $currentTheme \Magento\Framework\View\Design\ThemeInterface */
- $currentTheme = $params['themeModel'];
- $key = $currentTheme->getCode();
- if (isset($this->viewConfigs[$key])) {
- return $this->viewConfigs[$key];
+ $viewConfigParams = [];
+
+ if (isset($params['themeModel'])) {
+ /** @var \Magento\Framework\View\Design\ThemeInterface $currentTheme */
+ $currentTheme = $params['themeModel'];
+ $key = $currentTheme->getFullPath();
+ if (isset($this->viewConfigs[$key])) {
+ return $this->viewConfigs[$key];
+ }
+ $viewConfigParams['themeModel'] = $currentTheme;
}
+ $viewConfigParams['area'] = (isset($params['area'])) ? $params['area'] : null;
- $config = $this->viewConfigFactory->create();
+ /** @var \Magento\Framework\Config\View $config */
+ $config = $this->viewConfigFactory->create($viewConfigParams);
- $this->viewConfigs[$key] = $config;
+ if (isset($key)) {
+ $this->viewConfigs[$key] = $config;
+ }
return $config;
}
}
diff --git a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Minification.php b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Minification.php
index 03d51faea2c69..aef2270c0957f 100644
--- a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Minification.php
+++ b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Minification.php
@@ -38,6 +38,7 @@ public function __construct(ResolverInterface $fallback, AssetMinification $mini
$this->fallback = $fallback;
$this->minification = $minification;
}
+
/**
* Get path of file after using fallback rules
*
@@ -51,8 +52,9 @@ public function __construct(ResolverInterface $fallback, AssetMinification $mini
*/
public function resolve($type, $file, $area = null, ThemeInterface $theme = null, $locale = null, $module = null)
{
+ $file = $this->minification->addMinifiedSign($file);
$path = $this->fallback->resolve($type, $file, $area, $theme, $locale, $module);
- if (!$path && $file != ($newFile = $this->minification->removeMinifiedSign($file))) {
+ if (!$path && ($newFile = $this->minification->removeMinifiedSign($file))) {
$path = $this->fallback->resolve($type, $newFile, $area, $theme, $locale, $module);
}
return $path;
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/Bundle/ManagerTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/Bundle/ManagerTest.php
index a9d06fb33309a..cb161a5c204df 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/Bundle/ManagerTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/Bundle/ManagerTest.php
@@ -30,23 +30,23 @@ class ManagerTest extends \PHPUnit_Framework_TestCase
/** @var \Magento\Framework\View\Asset\Minification|\PHPUnit_Framework_MockObject_MockObject */
private $minificationMock;
- public function setUp()
+ protected function setUp()
{
- $this->filesystem = $this->getMockBuilder('Magento\Framework\Filesystem')
+ $this->filesystem = $this->getMockBuilder(\Magento\Framework\Filesystem::class)
->disableOriginalConstructor()
->getMock();
- $this->bundle = $this->getMockBuilder('Magento\Framework\View\Asset\Bundle')
+ $this->bundle = $this->getMockBuilder(\Magento\Framework\View\Asset\Bundle::class)
->disableOriginalConstructor()
->getMock();
- $this->bundleConfig = $this->getMockBuilder('Magento\Framework\View\Asset\Bundle\ConfigInterface')
+ $this->bundleConfig = $this->getMockBuilder(\Magento\Framework\View\Asset\Bundle\ConfigInterface::class)
->disableOriginalConstructor()
->getMock();
- $this->assetConfig = $this->getMockBuilder('Magento\Framework\View\Asset\ConfigInterface')
+ $this->assetConfig = $this->getMockBuilder(\Magento\Framework\View\Asset\ConfigInterface::class)
->disableOriginalConstructor()
->getMock();
$this->asset = $this->getMockForAbstractClass(
- 'Magento\Framework\View\Asset\LocalInterface',
+ \Magento\Framework\View\Asset\LocalInterface::class,
[],
'',
false,
@@ -55,7 +55,7 @@ public function setUp()
['getContentType']
);
- $this->minificationMock = $this->getMockBuilder('Magento\Framework\View\Asset\Minification')
+ $this->minificationMock = $this->getMockBuilder(\Magento\Framework\View\Asset\Minification::class)
->disableOriginalConstructor()
->getMock();
@@ -77,27 +77,15 @@ public function testAddAssetWithInvalidType()
$this->assertFalse($this->manager->addAsset($this->asset));
}
- public function testAddAssetWithHtmlTypeAndWithoutModule()
- {
- $this->asset->expects($this->once())
- ->method('getContentType')
- ->willReturn('html');
- $this->asset->expects($this->once())
- ->method('getModule')
- ->willReturn('');
-
- $this->assertFalse($this->manager->addAsset($this->asset));
- }
-
public function testAddAssetWithExcludedFile()
{
- $dirRead = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\ReadInterface')
+ $dirRead = $this->getMockBuilder(\Magento\Framework\Filesystem\Directory\ReadInterface::class)
->disableOriginalConstructor()
->getMock();
- $context = $this->getMockBuilder('Magento\Framework\View\Asset\File\FallbackContext')
+ $context = $this->getMockBuilder(\Magento\Framework\View\Asset\File\FallbackContext::class)
->disableOriginalConstructor()
->getMock();
- $configView = $this->getMockBuilder('Magento\Framework\Config\View')
+ $configView = $this->getMockBuilder(\Magento\Framework\Config\View::class)
->setMockClassName('configView')
->disableOriginalConstructor()
->getMock();
@@ -114,6 +102,9 @@ public function testAddAssetWithExcludedFile()
$this->asset->expects($this->atLeastOnce())
->method('getSourceFile')
->willReturn('source/file.min.js');
+ $this->asset->expects($this->atLeastOnce())
+ ->method('getFilePath')
+ ->willReturn('source/file.min.js');
$this->filesystem->expects($this->once())
->method('getDirectoryRead')
->with(\Magento\Framework\App\Filesystem\DirectoryList::APP)
@@ -131,13 +122,13 @@ public function testAddAssetWithExcludedFile()
public function testAddAssetWithExcludedDirectory()
{
- $dirRead = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\ReadInterface')
+ $dirRead = $this->getMockBuilder(\Magento\Framework\Filesystem\Directory\ReadInterface::class)
->disableOriginalConstructor()
->getMock();
- $context = $this->getMockBuilder('Magento\Framework\View\Asset\File\FallbackContext')
+ $context = $this->getMockBuilder(\Magento\Framework\View\Asset\File\FallbackContext::class)
->disableOriginalConstructor()
->getMock();
- $configView = $this->getMockBuilder('Magento\Framework\Config\View')
+ $configView = $this->getMockBuilder(\Magento\Framework\Config\View::class)
->disableOriginalConstructor()
->getMock();
@@ -183,13 +174,13 @@ public function testAddAssetWithExcludedDirectory()
public function testAddAsset()
{
- $dirRead = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\ReadInterface')
+ $dirRead = $this->getMockBuilder(\Magento\Framework\Filesystem\Directory\ReadInterface::class)
->disableOriginalConstructor()
->getMock();
- $context = $this->getMockBuilder('Magento\Framework\View\Asset\File\FallbackContext')
+ $context = $this->getMockBuilder(\Magento\Framework\View\Asset\File\FallbackContext::class)
->disableOriginalConstructor()
->getMock();
- $configView = $this->getMockBuilder('Magento\Framework\Config\View')
+ $configView = $this->getMockBuilder(\Magento\Framework\Config\View::class)
->disableOriginalConstructor()
->getMock();
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/BundleTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/BundleTest.php
index 8b1cdbb74fde1..8bfc7ba6f8c91 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/BundleTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/BundleTest.php
@@ -68,12 +68,12 @@ public function testMinSuffix()
->withConsecutive(
['onefile.js'],
['onefile.js'],
- ['/js/bundle/bundle0.js']
+ ['path-to-theme/js/bundle/bundle0.js']
)
->willReturnOnConsecutiveCalls(
'onefile.min.js',
'onefile.min.js',
- '/js/bundle/bundle0.min.js'
+ 'path-to-theme/js/bundle/bundle0.min.js'
);
$contextMock = $this->getMockBuilder('Magento\Framework\View\Asset\File\FallbackContext')
@@ -91,6 +91,10 @@ public function testMinSuffix()
->expects($this->any())
->method('getLocale')
->willReturn('locale');
+ $contextMock
+ ->expects($this->any())
+ ->method('getPath')
+ ->willReturn('path-to-theme');
$assetMock = $this->getMockBuilder('Magento\Framework\View\Asset\LocalInterface')
->setMethods(['getContentType', 'getContext'])
@@ -110,10 +114,14 @@ public function testMinSuffix()
$writeMock = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\WriteInterface')
->getMockForAbstractClass();
+ $writeMock
+ ->expects($this->once())
+ ->method('delete')
+ ->with('path-to-theme' . DIRECTORY_SEPARATOR . \Magento\Framework\View\Asset\Bundle\Manager::BUNDLE_JS_DIR);
$writeMock
->expects($this->once())
->method('writeFile')
- ->with('/js/bundle/bundle0.min.js', $this->stringContains('onefile.min.js'));
+ ->with('path-to-theme/js/bundle/bundle0.min.js', $this->stringContains('onefile.min.js'));
$this->filesystemMock
->expects($this->any())
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/LockerProcessTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/LockerProcessTest.php
index 91666d0838cea..49314f9a23f8f 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/LockerProcessTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/LockerProcessTest.php
@@ -9,6 +9,8 @@
use Magento\Framework\View\Asset\LockerProcess;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem\Directory\WriteInterface;
+use Magento\Framework\App\State;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
/**
* Class LockerProcessTest
@@ -34,6 +36,11 @@ class LockerProcessTest extends \PHPUnit_Framework_TestCase
*/
private $filesystemMock;
+ /**
+ * @var State|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $stateMock;
+
/**
* Set up
*/
@@ -44,8 +51,20 @@ protected function setUp()
$this->filesystemMock = $this->getMockBuilder('Magento\Framework\Filesystem')
->disableOriginalConstructor()
->getMock();
+ $this->stateMock = $this->getMockBuilder(State::class)
+ ->disableOriginalConstructor()
+ ->getMock();
- $this->lockerProcess = new LockerProcess($this->filesystemMock);
+ $this->lockerProcess = (new ObjectManager($this))->getObject(
+ LockerProcess::class,
+ [
+ 'filesystem' => $this->filesystemMock,
+ ]
+ );
+ $reflection = new \ReflectionClass(LockerProcess::class);
+ $reflectionProperty = $reflection->getProperty('state');
+ $reflectionProperty->setAccessible(true);
+ $reflectionProperty->setValue($this->lockerProcess, $this->stateMock);
}
/**
@@ -57,6 +76,7 @@ protected function setUp()
*/
public function testLockProcess($method)
{
+ $this->stateMock->expects(self::once())->method('getMode')->willReturn(State::MODE_DEVELOPER);
$this->filesystemMock->expects(self::once())
->method('getDirectoryWrite')
->with(DirectoryList::VAR_DIR)
@@ -65,11 +85,20 @@ public function testLockProcess($method)
$this->lockerProcess->lockProcess(self::LOCK_NAME);
}
+ public function testNotLockProcessInProductionMode()
+ {
+ $this->stateMock->expects(self::once())->method('getMode')->willReturn(State::MODE_PRODUCTION);
+ $this->filesystemMock->expects($this->never())->method('getDirectoryWrite');
+
+ $this->lockerProcess->lockProcess(self::LOCK_NAME);
+ }
+
/**
* Test for unlockProcess method
*/
public function testUnlockProcess()
{
+ $this->stateMock->expects(self::exactly(2))->method('getMode')->willReturn(State::MODE_DEVELOPER);
$this->filesystemMock->expects(self::once())
->method('getDirectoryWrite')
->with(DirectoryList::VAR_DIR)
@@ -79,6 +108,15 @@ public function testUnlockProcess()
$this->lockerProcess->unlockProcess();
}
+ public function testNotUnlockProcessInProductionMode()
+ {
+ $this->stateMock->expects(self::exactly(2))->method('getMode')->willReturn(State::MODE_PRODUCTION);
+ $this->filesystemMock->expects(self::never())->method('getDirectoryWrite');
+
+ $this->lockerProcess->lockProcess(self::LOCK_NAME);
+ $this->lockerProcess->unlockProcess();
+ }
+
/**
* @return array
*/
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/RepositoryTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/RepositoryTest.php
index cadb00c259fff..7aad0b9b6df15 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/RepositoryTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/RepositoryTest.php
@@ -6,10 +6,13 @@
namespace Magento\Framework\View\Test\Unit\Asset;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Framework\View\Asset\Repository;
+use Magento\Framework\View\Design\Theme\ThemeProviderInterface;
/**
* Unit test for Magento\Framework\View\Asset\Repository
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class RepositoryTest extends \PHPUnit_Framework_TestCase
{
@@ -31,7 +34,7 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase
/**
* @var \Magento\Framework\View\Design\Theme\ListInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- private $listMock;
+ private $themeProvider;
/**
* @var \Magento\Framework\View\Asset\Source|\PHPUnit_Framework_MockObject_MockObject
@@ -74,7 +77,7 @@ protected function setUp()
$this->designMock = $this->getMockBuilder('Magento\Framework\View\DesignInterface')
->disableOriginalConstructor()
->getMock();
- $this->listMock = $this->getMockBuilder('Magento\Framework\View\Design\Theme\ListInterface')
+ $this->themeProvider = $this->getMockBuilder(ThemeProviderInterface::class)
->disableOriginalConstructor()
->getMock();
$this->sourceMock = $this->getMockBuilder('Magento\Framework\View\Asset\Source')
@@ -99,17 +102,21 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();
- $this->repository = new Repository(
- $this->urlMock,
- $this->designMock,
- $this->listMock,
- $this->sourceMock,
- $this->httpMock,
- $this->fileFactoryMock,
- $this->fallbackFactoryMock,
- $this->contextFactoryMock,
- $this->remoteFactoryMock
- );
+ $this->repository = (new ObjectManager($this))->getObject(Repository::class, [
+ 'baseUrl' => $this->urlMock,
+ 'design' => $this->designMock,
+ 'assetSource' => $this->sourceMock,
+ 'request' => $this->httpMock,
+ 'fileFactory' => $this->fileFactoryMock,
+ 'fallbackContextFactory' => $this->fallbackFactoryMock,
+ 'contextFactory' => $this->contextFactoryMock,
+ 'remoteFactory' => $this->remoteFactoryMock
+ ]);
+
+ $reflection = new \ReflectionClass(Repository::class);
+ $reflectionProperty = $reflection->getProperty('themeProvider');
+ $reflectionProperty->setAccessible(true);
+ $reflectionProperty->setValue($this->repository, $this->themeProvider);
}
/**
@@ -120,7 +127,7 @@ protected function setUp()
public function testUpdateDesignParamsWrongTheme()
{
$params = ['area' => 'area', 'theme' => 'nonexistent_theme'];
- $this->listMock->expects($this->once())
+ $this->themeProvider->expects($this->once())
->method('getThemeByFullPath')
->with('area/nonexistent_theme')
->will($this->returnValue(null));
@@ -135,7 +142,7 @@ public function testUpdateDesignParamsWrongTheme()
*/
public function testUpdateDesignParams($params, $result)
{
- $this->listMock
+ $this->themeProvider
->expects($this->any())
->method('getThemeByFullPath')
->willReturn('ThemeID');
@@ -165,7 +172,7 @@ public function updateDesignParamsDataProvider()
*/
public function testCreateAsset()
{
- $this->listMock
+ $this->themeProvider
->expects($this->any())
->method('getThemeByFullPath')
->willReturnArgument(0);
@@ -227,7 +234,7 @@ public function testGetStaticViewFileContext()
'locale' => 'locale'
]
);
- $this->listMock
+ $this->themeProvider
->expects($this->any())
->method('getThemeByFullPath')
->willReturnArgument(0);
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/SourceTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/SourceTest.php
index eecafdfe6dd46..3e7549e881616 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/SourceTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/SourceTest.php
@@ -10,9 +10,11 @@
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem\DriverPool;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Framework\View\Asset\PreProcessor\ChainFactoryInterface;
use Magento\Framework\View\Asset\PreProcessor\Chain;
use Magento\Framework\View\Asset\Source;
+use Magento\Framework\View\Design\Theme\ThemeProviderInterface;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -90,17 +92,25 @@ protected function setUp()
->method('create')
->willReturn($this->chain);
- $themeList = $this->getMockForAbstractClass('Magento\Framework\View\Design\Theme\ListInterface');
- $themeList->expects($this->any())
+ $themeProvider = $this->getMock(ThemeProviderInterface::class);
+ $themeProvider->expects($this->any())
->method('getThemeByFullPath')
->with('frontend/magento_theme')
->willReturn($this->theme);
$this->initFilesystem();
- $this->object = new Source(
- $this->filesystem, $this->preProcessorPool, $this->viewFileResolution, $themeList, $this->chainFactory
- );
+ $this->object = (new ObjectManager($this))->getObject(Source::class, [
+ 'filesystem' => $this->filesystem,
+ 'preProcessorPool' => $this->preProcessorPool,
+ 'fallback' => $this->viewFileResolution,
+ 'chainFactory' => $this->chainFactory
+ ]);
+
+ $reflection = new \ReflectionClass(Source::class);
+ $reflectionProperty = $reflection->getProperty('themeProvider');
+ $reflectionProperty->setAccessible(true);
+ $reflectionProperty->setValue($this->object, $themeProvider);
}
/**
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/ConfigTest.php b/lib/internal/Magento/Framework/View/Test/Unit/ConfigTest.php
index 8247cd83bab4e..2a09783c710e4 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/ConfigTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/ConfigTest.php
@@ -6,7 +6,6 @@
namespace Magento\Framework\View\Test\Unit;
-use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
class ConfigTest extends \PHPUnit_Framework_TestCase
@@ -27,11 +26,11 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
- $this->repositoryMock = $this->getMock('Magento\Framework\View\Asset\Repository', [], [], '', false);
- $this->viewConfigFactoryMock = $this->getMock('Magento\Framework\Config\ViewFactory', [], [], '', false);
+ $this->repositoryMock = $this->getMock(\Magento\Framework\View\Asset\Repository::class, [], [], '', false);
+ $this->viewConfigFactoryMock = $this->getMock(\Magento\Framework\Config\ViewFactory::class, [], [], '', false);
$this->objectManagerHelper = new ObjectManagerHelper($this);
$this->config = $this->objectManagerHelper->getObject(
- 'Magento\Framework\View\Config',
+ \Magento\Framework\View\Config::class,
[
'assetRepo' => $this->repositoryMock,
'viewConfigFactory' => $this->viewConfigFactoryMock
@@ -41,27 +40,32 @@ protected function setUp()
public function testGetViewConfig()
{
+ $themeCode = 'area/theme';
+
$themeMock = $this->getMock(
- 'Magento\Theme\Model\Theme',
- ['getCode'],
+ \Magento\Theme\Model\Theme::class,
+ ['getFullPath'],
[],
'',
false
);
$themeMock->expects($this->atLeastOnce())
- ->method('getCode')
- ->will($this->returnValue(2));
- $params = ['themeModel' => $themeMock];
+ ->method('getFullPath')
+ ->will($this->returnValue($themeCode));
+ $params = [
+ 'themeModel' => $themeMock,
+ 'area' => 'frontend'
+ ];
$this->repositoryMock->expects($this->atLeastOnce())
->method('updateDesignParams')
->with($this->equalTo($params))
->will($this->returnSelf());
- $configViewMock = $this->getMock('Magento\Framework\Config\View', [], [], '', false);
+ $configViewMock = $this->getMock(\Magento\Framework\Config\View::class, [], [], '', false);
$this->viewConfigFactoryMock->expects($this->once())
->method('create')
->willReturn($configViewMock);
- $this->assertInstanceOf('Magento\Framework\Config\View', $this->config->getViewConfig($params));
+ $this->assertInstanceOf(\Magento\Framework\Config\View::class, $this->config->getViewConfig($params));
// lazy load test
- $this->assertInstanceOf('Magento\Framework\Config\View', $this->config->getViewConfig($params));
+ $this->assertInstanceOf(\Magento\Framework\Config\View::class, $this->config->getViewConfig($params));
}
}
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/MinificationTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/MinificationTest.php
index 48646023685d2..3f461f1602247 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/MinificationTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/MinificationTest.php
@@ -28,17 +28,18 @@ class MinificationTest extends \PHPUnit_Framework_TestCase
* @var \Magento\Framework\View\Asset\Minification|\PHPUnit_Framework_MockObject_MockObject
*/
protected $assetMinificationMock;
+
/**
* {@inheritDoc}
*/
protected function setUp()
{
$this->resolverMock = $this
- ->getMockBuilder('Magento\Framework\View\Design\FileResolution\Fallback\ResolverInterface')
+ ->getMockBuilder(\Magento\Framework\View\Design\FileResolution\Fallback\ResolverInterface::class)
->disableOriginalConstructor()
->getMock();
- $this->assetMinificationMock = $this->getMockBuilder('Magento\Framework\View\Asset\Minification')
+ $this->assetMinificationMock = $this->getMockBuilder(\Magento\Framework\View\Asset\Minification::class)
->disableOriginalConstructor()
->getMock();
@@ -69,21 +70,20 @@ public function testResolve(
$this->assetMinificationMock
->expects($this->any())
->method('isEnabled')
- ->willReturnMap([['css', $isEnabled]]);
+ ->willReturn($isEnabled);
$this->assetMinificationMock
->expects($this->any())
- ->method('removeMinifiedSign')
+ ->method('addMinifiedSign')
->with($requested)
->willReturn($alternative);
$this->resolverMock
->expects($this->any())
->method('resolve')
- ->withConsecutive(
- ['', $requested, null, null, null, null],
- ['', $alternative, null, null, null, null]
- )
- ->willReturnOnConsecutiveCalls($resolvedOriginal, $resolvedAlternative);
+ ->willReturnMap([
+ ['', $requested, null, null, null, null, $resolvedOriginal],
+ ['', $alternative, null, null, null, null, $resolvedAlternative]
+ ]);
$this->assertEquals($expected, $this->minification->resolve('', $requested));
}
@@ -94,8 +94,10 @@ public function testResolve(
public function resolveDataProvider()
{
return [
- [true, 'file.min.css', 'file.css', 'found.css', false, 'found.css'],
- [false, 'file.min.css', 'file.min.css', false, false, 'found.css']
+ [true, 'file.css', 'file.min.css', 'found.min.css', false, 'found.min.css'],
+ [false, 'file.min.css', 'file.min.css', false, false, 'found.css'],
+ [true, 'file.js', 'file.min.js', 'found.min.js', false, 'found.min.js'],
+ [false, 'file.min.js', 'file.min.js', false, false, 'found.js'],
];
}
}
diff --git a/setup/config/di.config.php b/setup/config/di.config.php
index 1fb42803996ed..9c73aae475358 100644
--- a/setup/config/di.config.php
+++ b/setup/config/di.config.php
@@ -38,6 +38,7 @@
'Magento\Setup\Controller\Marketplace',
'Magento\Setup\Controller\SystemConfig',
'Magento\Setup\Controller\InstallExtensionGrid',
+ 'Magento\Setup\Controller\MarketplaceCredentials',
'Magento\Setup\Controller\Session'
],
'instance' => [
diff --git a/setup/config/states.home.config.php b/setup/config/states.home.config.php
index 78e947b2ee7b1..ddb6c7430248f 100644
--- a/setup/config/states.home.config.php
+++ b/setup/config/states.home.config.php
@@ -49,13 +49,13 @@
],
[
'id' => 'root.upgrade',
- 'url' => 'select-version',
- 'templateUrl' => "$base/select-version",
+ 'url' => 'marketplace-credentials',
+ 'templateUrl' => "$base/marketplace-credentials",
'title' => 'System Upgrade',
- 'controller' => 'selectVersionController',
- 'header' => 'Step 1: Select Version',
+ 'controller' => 'MarketplaceCredentialsController',
'order' => 1,
- 'nav' => true,
+ 'nav' => false,
+ 'noMenu' => true,
'type' => 'upgrade'
],
],
diff --git a/setup/config/states.upgrade.config.php b/setup/config/states.upgrade.config.php
index c210cb7c1facc..dd1f8938f4581 100644
--- a/setup/config/states.upgrade.config.php
+++ b/setup/config/states.upgrade.config.php
@@ -11,13 +11,24 @@
'upgrade' => 'System Upgrade',
],
'navUpdater' => [
+ [
+ 'id' => 'root.select-version',
+ 'url' => 'select-version',
+ 'templateUrl' => "$base/select-version",
+ 'title' => 'System Upgrade',
+ 'controller' => 'selectVersionController',
+ 'header' => 'Step 1: Select Version',
+ 'order' => 2,
+ 'nav' => true,
+ 'type' => 'upgrade'
+ ],
[
'id' => 'root.readiness-check-upgrade',
'url' => 'readiness-check-updater',
'templateUrl' => "$base/readiness-check-updater",
'title' => "Readiness \n Check",
'header' => 'Step 2: Readiness Check',
- 'order' => 2,
+ 'order' => 3,
'nav' => true,
'type' => 'upgrade'
],
@@ -29,7 +40,7 @@
'header' => 'Step 2: Readiness Check',
'controller' => 'readinessCheckController',
'nav' => false,
- 'order' => 3,
+ 'order' => 4,
'type' => 'upgrade'
],
[
@@ -39,7 +50,7 @@
'title' => 'Create Backup',
'controller' => 'createBackupController',
'header' => 'Step 3: Create Backup',
- 'order' => 4,
+ 'order' => 5,
'nav' => true,
'type' => 'upgrade'
],
@@ -51,7 +62,7 @@
'header' => 'Step 3: Create Backup',
'controller' => 'completeBackupController',
'nav' => false,
- 'order' => 5,
+ 'order' => 6,
'type' => 'upgrade'
],
[
@@ -61,7 +72,7 @@
'title' => "System \n Upgrade",
'controller' => 'startUpdaterController',
'header' => 'Step 4: System Upgrade',
- 'order' => 6,
+ 'order' => 7,
'nav' => true,
'type' => 'upgrade'
],
@@ -70,7 +81,7 @@
'url' => 'updater-success',
'templateUrl' => "$base/updater-success",
'controller' => 'updaterSuccessController',
- 'order' => 7,
+ 'order' => 8,
'noMenu' => true
],
[
diff --git a/setup/pub/magento/setup/app.js b/setup/pub/magento/setup/app.js
index 71d9c50b4e8ef..7da6d4dae759b 100644
--- a/setup/pub/magento/setup/app.js
+++ b/setup/pub/magento/setup/app.js
@@ -28,7 +28,8 @@ var app = angular.module(
'updater-success',
'home',
'auth-dialog',
- 'system-config'
+ 'system-config',
+ 'marketplace-credentials'
]);
app.config(['$httpProvider', '$stateProvider', function ($httpProvider, $stateProvider) {
diff --git a/setup/pub/magento/setup/marketplace-credentials.js b/setup/pub/magento/setup/marketplace-credentials.js
new file mode 100644
index 0000000000000..1d1071063d139
--- /dev/null
+++ b/setup/pub/magento/setup/marketplace-credentials.js
@@ -0,0 +1,87 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+'use strict';
+angular.module('marketplace-credentials', ['ngStorage'])
+ .controller('MarketplaceCredentialsController', ['$scope', '$state', '$http', '$localStorage', '$rootScope', '$sce',
+ function ($scope, $state, $http, $localStorage, $rootScope, $sce) {
+ $scope.showCredsForm = false;
+ $scope.user = {
+ username : $localStorage.marketplaceUsername ? $localStorage.marketplaceUsername : '',
+ password : '',
+ submitted : false
+ };
+
+ $scope.upgradeProcessError = false;
+
+ $http.get('index.php/select-version/installedSystemPackage', {'responseType' : 'json'})
+ .success(function (data) {
+ if (data.responseType == 'error') {
+ $scope.upgradeProcessError = true;
+ $scope.upgradeProcessErrorMessage = $sce.trustAsHtml(data.error);
+ } else {
+ if (!$rootScope.authRequest || !$rootScope.isMarketplaceAuthorized) {
+ $scope.isHiddenSpinner = false;
+ $http.post('index.php/marketplace/check-auth', [])
+ .success(function (response) {
+ if (response.success) {
+ $localStorage.marketplaceUsername = $scope.user.username = response.data.username;
+ $localStorage.isMarketplaceAuthorized = true;
+ $scope.nextState();
+ } else {
+ $localStorage.isMarketplaceAuthorized = false;
+ $scope.showCredsForm = true;
+ }
+ $rootScope.isMarketplaceAuthorized = $localStorage.isMarketplaceAuthorized;
+ $rootScope.authRequest = true;
+ });
+ } else {
+ $rootScope.isMarketplaceAuthorized = $localStorage.isMarketplaceAuthorized;
+ $scope.nextState();
+ }
+ }
+ })
+ .error(function (data) {
+ $scope.upgradeProcessError = true;
+ });
+
+ $scope.errors = false;
+
+ $scope.saveAuthJson = function () {
+ if ($scope.auth.$valid) {
+ $http.post('index.php/marketplace/save-auth-json', $scope.user)
+ .success(function (data) {
+ $scope.saveAuthJson.result = data;
+ if ($scope.saveAuthJson.result.success) {
+ $scope.logout = false;
+ $localStorage.isMarketplaceAuthorized = true;
+ $scope.errors = false;
+ $scope.nextState();
+ } else {
+ $localStorage.isMarketplaceAuthorized = false;
+ $scope.errors = true;
+ }
+ $rootScope.isMarketplaceAuthorized = $localStorage.isMarketplaceAuthorized;
+ $localStorage.marketplaceUsername = $scope.user.username;
+ })
+ .error(function (data) {
+ $scope.saveAuthJson.failed = data;
+ $localStorage.isMarketplaceAuthorized = false;
+ $scope.errors = true;
+
+ });
+ } else {
+ $scope.validate();
+ }
+ };
+
+ $scope.validate = function() {
+ if ($scope.user.$valid) {
+ $scope.user.submitted = false;
+ } else {
+ $scope.user.submitted = true;
+ }
+ }
+ }]);
diff --git a/setup/pub/magento/setup/select-version.js b/setup/pub/magento/setup/select-version.js
index 319055c5f6361..8e9eba9c5c413 100644
--- a/setup/pub/magento/setup/select-version.js
+++ b/setup/pub/magento/setup/select-version.js
@@ -5,7 +5,7 @@
'use strict';
angular.module('select-version', ['ngStorage'])
- .controller('selectVersionController', ['$scope', '$http', '$localStorage', function ($scope, $http, $localStorage) {
+ .controller('selectVersionController', ['$scope', '$http', '$localStorage', '$sce', function ($scope, $http, $localStorage, $sce) {
$scope.packages = [{
name: '',
version: ''
@@ -13,6 +13,7 @@ angular.module('select-version', ['ngStorage'])
$scope.upgradeReadyForNext = false;
$scope.upgradeProcessed = false;
$scope.upgradeProcessError = false;
+ $scope.upgradeProcessErrorMessage = '';
$scope.componentsReadyForNext = true;
$scope.componentsProcessed = false;
$scope.componentsProcessError = false;
@@ -27,33 +28,39 @@ angular.module('select-version', ['ngStorage'])
$http.get('index.php/select-version/systemPackage', {'responseType' : 'json'})
.success(function (data) {
if (data.responseType != 'error') {
- $scope.selectedOption = [];
- $scope.versions = [];
- for (var i = 0; i < data.packages.length; i++) {
- angular.forEach(data.packages[i].versions, function (value, key) {
- $scope.versions.push({
- 'versionInfo': angular.toJson({
- 'package': data.packages[i].package,
- 'version': value
- }), 'version': value
+ if (data.packages.length == 1 && data.packages[0].versions.length <=1) {
+ $scope.upgradeProcessError = true;
+ $scope.upgradeProcessErrorMessage = "You're already using the latest version, there's nothing for us to do.";
+ } else {
+ $scope.selectedOption = [];
+ $scope.versions = [];
+ for (var i = 0; i < data.packages.length; i++) {
+ angular.forEach(data.packages[i].versions, function (value, key) {
+ $scope.versions.push({
+ 'versionInfo': angular.toJson({
+ 'package': data.packages[i].package,
+ 'version': value
+ }), 'version': value
+ });
});
+ }
+
+ $scope.versions = $scope.versions.sort(function (a, b) {
+ if (a.version.id < b.version.id) {
+ return 1;
+ }
+ if (a.version.id > b.version.id) {
+ return -1;
+ }
+ return 0;
});
+ $scope.selectedOption = $scope.versions[0].versionInfo;
+ $scope.upgradeReadyForNext = true;
}
- $scope.versions = $scope.versions.sort(function (a, b) {
- if (a.version.id < b.version.id) {
- return 1;
- }
- if (a.version.id > b.version.id) {
- return -1;
- }
- return 0;
- });
- $scope.selectedOption = $scope.versions[0].versionInfo;
- $scope.upgradeReadyForNext = true;
-
} else {
$scope.upgradeProcessError = true;
+ $scope.upgradeProcessErrorMessage = $sce.trustAsHtml(data.error);
}
$scope.upgradeProcessed = true;
})
diff --git a/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php b/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php
index 484ea598d9f31..908ba13afb70b 100644
--- a/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php
@@ -151,17 +151,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
'library' => $libraryPaths,
'generated_helpers' => $generationPath
];
- $excludedModulePaths = [];
- foreach ($modulePaths as $appCodePath) {
- $excludedModulePaths[] = '#^' . $appCodePath . '/Test#';
- }
- $excludedLibraryPaths = [];
- foreach ($libraryPaths as $libraryPath) {
- $excludedLibraryPaths[] = '#^' . $libraryPath . '/([\\w]+/)?Test#';
- }
$this->excludedPathsList = [
- 'application' => $excludedModulePaths,
- 'framework' => $excludedLibraryPaths
+ 'application' => $this->getExcludedModulePaths($modulePaths),
+ 'framework' => $this->getExcludedLibraryPaths($libraryPaths),
];
$this->configureObjectManager($output);
@@ -214,6 +206,54 @@ function (OperationInterface $operation) use ($progressBar) {
}
}
+ /**
+ * Build list of module path regexps which should be excluded from compilation
+ *
+ * @param string[] $modulePaths
+ * @return string[]
+ */
+ private function getExcludedModulePaths(array $modulePaths)
+ {
+ $modulesByBasePath = [];
+ foreach ($modulePaths as $modulePath) {
+ $moduleDir = basename($modulePath);
+ $vendorPath = dirname($modulePath);
+ $vendorDir = basename($vendorPath);
+ $basePath = dirname($vendorPath);
+ $modulesByBasePath[$basePath][$vendorDir][] = $moduleDir;
+ }
+
+ $basePathsRegExps = [];
+ foreach ($modulesByBasePath as $basePath => $vendorPaths) {
+ $vendorPathsRegExps = [];
+ foreach ($vendorPaths as $vendorDir => $vendorModules) {
+ $vendorPathsRegExps[] = $vendorDir
+ . '/(?:' . join('|', $vendorModules) . ')';
+ }
+ $basePathsRegExps[] = $basePath
+ . '/(?:' . join('|', $vendorPathsRegExps) . ')';
+ }
+
+ $excludedModulePaths = [
+ '#^(?:' . join('|', $basePathsRegExps) . ')/Test#',
+ ];
+ return $excludedModulePaths;
+ }
+
+ /**
+ * Build list of library path regexps which should be excluded from compilation
+ *
+ * @param string[] $libraryPaths
+ * @return string[]
+ */
+ private function getExcludedLibraryPaths(array $libraryPaths)
+ {
+ $excludedLibraryPaths = [
+ '#^(?:' . join('|', $libraryPaths) . ')/([\\w]+/)?Test#',
+ ];
+ return $excludedLibraryPaths;
+ }
+
/**
* Delete directories by their code from "var" directory
*
diff --git a/setup/src/Magento/Setup/Controller/ComponentGrid.php b/setup/src/Magento/Setup/Controller/ComponentGrid.php
index a3db50df89fe8..9d97cf7ae3cfe 100644
--- a/setup/src/Magento/Setup/Controller/ComponentGrid.php
+++ b/setup/src/Magento/Setup/Controller/ComponentGrid.php
@@ -63,12 +63,14 @@ class ComponentGrid extends \Zend\Mvc\Controller\AbstractActionController
* @param \Magento\Setup\Model\ObjectManagerProvider $objectManagerProvider
* @param \Magento\Setup\Model\UpdatePackagesCache $updatePackagesCache
* @param \Magento\Setup\Model\MarketplaceManager $marketplaceManager
+ * @param TimezoneProvider $timezoneProvider
*/
public function __construct(
\Magento\Framework\Composer\ComposerInformation $composerInformation,
\Magento\Setup\Model\ObjectManagerProvider $objectManagerProvider,
\Magento\Setup\Model\UpdatePackagesCache $updatePackagesCache,
- \Magento\Setup\Model\MarketplaceManager $marketplaceManager
+ \Magento\Setup\Model\MarketplaceManager $marketplaceManager,
+ \Magento\Setup\Model\DateTime\TimezoneProvider $timezoneProvider
) {
$this->composerInformation = $composerInformation;
$this->objectManager = $objectManagerProvider->get();
@@ -77,34 +79,7 @@ public function __construct(
$this->packageInfo = $this->objectManager->get('Magento\Framework\Module\PackageInfoFactory')->create();
$this->marketplaceManager = $marketplaceManager;
$this->updatePackagesCache = $updatePackagesCache;
- }
-
- /**
- * Get timezone
- *
- * @return \Magento\Framework\Stdlib\DateTime\TimezoneInterface|null
- */
- private function getTimezone()
- {
- if ($this->timezone === null) {
- $this->timezone = $this->objectManager->get('Magento\Setup\Model\DateTime\TimezoneProvider')->get();
- }
- return $this->timezone;
- }
-
- /**
- * Set timezone
- *
- * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone
- * @return void
- * @throws \Exception
- */
- public function setTimezone(\Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone)
- {
- if ($this->timezone !== null) {
- throw new \Exception('timezone is already set');
- }
- $this->timezone = $timezone;
+ $this->timezone = $timezoneProvider->get();
}
/**
@@ -182,18 +157,18 @@ public function componentsAction()
public function syncAction()
{
$error = '';
+ $packagesForInstall = [];
+ $lastSyncData = [];
try {
$this->updatePackagesCache->syncPackagesForUpdate();
$lastSyncData = $this->updatePackagesCache->getPackagesForUpdate();
$this->marketplaceManager->syncPackagesForInstall();
$packagesForInstall = $this->marketplaceManager->getPackagesForInstall();
+ $lastSyncData = $this->formatLastSyncData($packagesForInstall, $lastSyncData);
} catch (\Exception $e) {
$error = $e->getMessage();
}
-
- $lastSyncData = $this->formatLastSyncData($packagesForInstall, $lastSyncData);
-
return new \Zend\View\Model\JsonModel(
[
'success' => true,
@@ -248,12 +223,12 @@ private function formatLastSyncData($packagesForInstall, $lastSyncData)
private function formatSyncDate($syncDate)
{
return [
- 'date' => $this->getTimezone()->formatDateTime(
+ 'date' => $this->timezone->formatDateTime(
new \DateTime('@'.$syncDate),
\IntlDateFormatter::MEDIUM,
\IntlDateFormatter::NONE
),
- 'time' => $this->getTimezone()->formatDateTime(
+ 'time' => $this->timezone->formatDateTime(
new \DateTime('@'.$syncDate),
\IntlDateFormatter::NONE,
\IntlDateFormatter::MEDIUM
diff --git a/setup/src/Magento/Setup/Controller/MarketplaceCredentials.php b/setup/src/Magento/Setup/Controller/MarketplaceCredentials.php
new file mode 100644
index 0000000000000..312b853688b0a
--- /dev/null
+++ b/setup/src/Magento/Setup/Controller/MarketplaceCredentials.php
@@ -0,0 +1,22 @@
+setTerminal(true);
+ return $view;
+ }
+}
diff --git a/setup/src/Magento/Setup/Controller/SelectVersion.php b/setup/src/Magento/Setup/Controller/SelectVersion.php
index d78194a23ee7b..5b1d11058fcc4 100644
--- a/setup/src/Magento/Setup/Controller/SelectVersion.php
+++ b/setup/src/Magento/Setup/Controller/SelectVersion.php
@@ -61,4 +61,22 @@ public function systemPackageAction()
return new JsonModel($data);
}
+
+ /**
+ * Gets installed system package
+ *
+ * @return JsonModel
+ */
+ public function installedSystemPackageAction()
+ {
+ $data = [];
+ try {
+ $data['packages'] = $this->systemPackage->getInstalledSystemPackages([]);
+ $data['responseType'] = ResponseTypeInterface::RESPONSE_TYPE_SUCCESS;
+ } catch (\Exception $e) {
+ $data['error'] = $e->getMessage();
+ $data['responseType'] = ResponseTypeInterface::RESPONSE_TYPE_ERROR;
+ }
+ return new JsonModel($data);
+ }
}
diff --git a/setup/src/Magento/Setup/Model/FilePermissions.php b/setup/src/Magento/Setup/Model/FilePermissions.php
index 43dc400a81e71..6863968ef3cd7 100644
--- a/setup/src/Magento/Setup/Model/FilePermissions.php
+++ b/setup/src/Magento/Setup/Model/FilePermissions.php
@@ -8,7 +8,9 @@
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Backup\Filesystem\Iterator\Filter;
+use Magento\Framework\Filesystem\Filter\ExcludeFilter;
use Magento\Framework\Filesystem;
+use Magento\Framework\Filesystem\Driver\File;
class FilePermissions
{
@@ -22,6 +24,11 @@ class FilePermissions
*/
protected $directoryList;
+ /**
+ * @var File
+ */
+ protected $driverFile;
+
/**
* List of required writable directories for installation
*
@@ -50,16 +57,26 @@ class FilePermissions
*/
protected $applicationCurrentNonWritableDirectories = [];
+ /**
+ * List of non-writable paths in a specified directory
+ *
+ * @var array
+ */
+ protected $nonWritablePathsInDirectories = [];
+
/**
* @param Filesystem $filesystem
* @param DirectoryList $directoryList
+ * @param File $driverFile
*/
public function __construct(
Filesystem $filesystem,
- DirectoryList $directoryList
+ DirectoryList $directoryList,
+ File $driverFile
) {
$this->filesystem = $filesystem;
$this->directoryList = $directoryList;
+ $this->driverFile = $driverFile;
}
/**
@@ -110,8 +127,12 @@ public function getInstallationCurrentWritableDirectories()
{
if (!$this->installationCurrentWritableDirectories) {
foreach ($this->installationWritableDirectories as $code => $path) {
- if ($this->isWritable($code) && $this->checkRecursiveDirectories($path)) {
- $this->installationCurrentWritableDirectories[] = $path;
+ if ($this->isWritable($code)) {
+ if ($this->checkRecursiveDirectories($path)) {
+ $this->installationCurrentWritableDirectories[] = $path;
+ }
+ } else {
+ $this->nonWritablePathsInDirectories[$path] = [$path];
}
}
}
@@ -132,21 +153,31 @@ private function checkRecursiveDirectories($directory)
);
$noWritableFilesFolders = [
$this->directoryList->getPath(DirectoryList::GENERATION) . '/',
- $this->directoryList->getPath(DirectoryList::DI) .'/'
+ $this->directoryList->getPath(DirectoryList::DI) . '/',
];
$directoryIterator = new Filter($directoryIterator, $noWritableFilesFolders);
+ $directoryIterator = new ExcludeFilter(
+ $directoryIterator,
+ [
+ $this->directoryList->getPath(DirectoryList::SESSION) . '/',
+ ]
+ );
+
+ $foundNonWritable = false;
+
try {
foreach ($directoryIterator as $subDirectory) {
- if (!$subDirectory->isWritable()) {
- return false;
+ if (!$subDirectory->isWritable() && !$subDirectory->isLink()) {
+ $this->nonWritablePathsInDirectories[$directory][] = $subDirectory;
+ $foundNonWritable = true;
}
}
} catch (\UnexpectedValueException $e) {
return false;
}
- return true;
+ return !$foundNonWritable;
}
/**
@@ -190,6 +221,28 @@ protected function isNonWritable($code)
return $this->isReadableDirectory($directory) && !$directory->isWritable();
}
+ /**
+ * Checks if var/generation/* has read and execute permissions
+ *
+ * @return bool
+ */
+ public function checkDirectoryPermissionForCLIUser()
+ {
+ $varGenerationDir = $this->directoryList->getPath(DirectoryList::GENERATION);
+ $dirs = $this->driverFile->readDirectory($varGenerationDir);
+ array_unshift($dirs, $varGenerationDir);
+
+ foreach ($dirs as $dir) {
+ if (!is_dir($dir)
+ || !is_readable($dir)
+ || !is_executable($dir)
+ ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* Checks if directory exists and is readable
*
@@ -204,9 +257,31 @@ protected function isReadableDirectory($directory)
return true;
}
+ /**
+ * Checks writable paths for installation
+ *
+ * @return array
+ */
+ public function getMissingWritablePathsForInstallation()
+ {
+ $required = $this->getInstallationWritableDirectories();
+ $current = $this->getInstallationCurrentWritableDirectories();
+ $missingPaths = [];
+ foreach (array_diff($required, $current) as $missingPath) {
+ if (isset($this->nonWritablePathsInDirectories[$missingPath])) {
+ $missingPaths = array_merge(
+ $missingPaths,
+ $this->nonWritablePathsInDirectories[$missingPath]
+ );
+ }
+ }
+ return $missingPaths;
+ }
+
/**
* Checks writable directories for installation
*
+ * @deprecated Use getMissingWritablePathsForInstallation() to get all missing writable paths required for install
* @return array
*/
public function getMissingWritableDirectoriesForInstallation()
diff --git a/setup/src/Magento/Setup/Model/MarketplaceManager.php b/setup/src/Magento/Setup/Model/MarketplaceManager.php
index b1d4e5c0d425a..75cf909c37531 100644
--- a/setup/src/Magento/Setup/Model/MarketplaceManager.php
+++ b/setup/src/Magento/Setup/Model/MarketplaceManager.php
@@ -166,14 +166,18 @@ public function syncPackagesForInstall()
}
$packageNames = array_column($this->getComposerInformation()->getInstalledMagentoPackages(), 'name');
$installPackages = [];
- foreach ($packagesJsonData['packages'] as $package) {
- $package = $this->unsetDevVersions($package);
- if (!empty($package)) {
+ foreach ($packagesJsonData['packages'] as $packageName => $package) {
+ if (!empty($package) && is_array($package)) {
+ $package = $this->unsetDevVersions($package);
ksort($package);
- $package = array_pop($package);
- if ($this->isNewUserPackage($package, $packageNames)) {
- $package['vendor'] = explode('/', $package['name'])[0];
- $installPackages[$package['name']] = $package;
+ $packageValues = array_values($package);
+ if ($this->isNewUserPackage($packageValues[0], $packageNames)) {
+ $versions = array_reverse(array_keys($package));
+ $installPackage = $packageValues[0];
+ $installPackage['versions'] = $versions;
+ $installPackage['name'] = $packageName;
+ $installPackage['vendor'] = explode('/', $packageName)[0];
+ $installPackages[$packageName] = $installPackage;
}
}
}
@@ -364,6 +368,7 @@ public function getPackagesForInstall()
$package['metapackage'] =
isset($metaPackageByPackage[$package['name']]) ? $metaPackageByPackage[$package['name']] : '';
$actualInstallackages[$package['name']] = $package;
+ $actualInstallackages[$package['name']]['version'] = $package['versions'][0];
}
}
$installPackagesInfo['packages'] = $actualInstallackages;
diff --git a/setup/src/Magento/Setup/Model/SystemPackage.php b/setup/src/Magento/Setup/Model/SystemPackage.php
index 3850ab9051ac9..6ac9b9d3a60bc 100755
--- a/setup/src/Magento/Setup/Model/SystemPackage.php
+++ b/setup/src/Magento/Setup/Model/SystemPackage.php
@@ -58,14 +58,11 @@ public function getPackageVersions()
$result = [];
$systemPackages = [];
$systemPackages = $this->getInstalledSystemPackages($systemPackages);
- if (empty($systemPackages)) {
- throw new \RuntimeException('System packages not found');
- }
foreach ($systemPackages as $systemPackage) {
$versions = [];
$systemPackageInfo = $this->infoCommand->run($systemPackage);
if (!$systemPackageInfo) {
- throw new \RuntimeException('System package not found');
+ throw new \RuntimeException("We cannot retrieve information on $systemPackage.");
}
$versions = $this->getSystemPackageVersions($systemPackageInfo, $versions);
@@ -150,6 +147,7 @@ public function getSystemPackageVersions($systemPackageInfo, $versions)
/**
* @param array $systemPackages
* @return array
+ * @throws \RuntimeException
*/
public function getInstalledSystemPackages($systemPackages)
{
@@ -169,6 +167,14 @@ public function getInstalledSystemPackages($systemPackages)
}
}
}
+ if (empty($systemPackages)) {
+ throw new \RuntimeException(
+ 'We\'re sorry, no components are available because you cloned the Magento 2 GitHub repository. ' .
+ 'You must manually update components as discussed in the ' .
+ '' .
+ 'Installation Guide .'
+ );
+ }
return $systemPackages;
}
diff --git a/setup/src/Magento/Setup/Model/UpdatePackagesCache.php b/setup/src/Magento/Setup/Model/UpdatePackagesCache.php
index a8e390db4e74d..e13125b5241de 100644
--- a/setup/src/Magento/Setup/Model/UpdatePackagesCache.php
+++ b/setup/src/Magento/Setup/Model/UpdatePackagesCache.php
@@ -11,7 +11,7 @@
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Framework\Composer\MagentoComposerApplicationFactory;
-use Magento\Framework\ObjectManagerInterface;
+use Magento\Setup\Model\DateTime\DateTimeProvider;
/**
* Class UpdatePackagesCache manages information about available for update packages though the cache file.
@@ -54,58 +54,24 @@ class UpdatePackagesCache
*/
private $pathToCacheFile = 'update_composer_packages.json';
- /**
- * @var ObjectManagerInterface
- */
- private $objectManager;
-
/**
* Constructor
*
* @param MagentoComposerApplicationFactory $applicationFactory
* @param \Magento\Framework\Filesystem $filesystem
* @param ComposerInformation $composerInformation
- * @param ObjectManagerProvider $objectManagerProvider
- * @throws \Exception
+ * @param DateTime\DateTimeProvider $dateTimeProvider
*/
public function __construct(
MagentoComposerApplicationFactory $applicationFactory,
Filesystem $filesystem,
ComposerInformation $composerInformation,
- ObjectManagerProvider $objectManagerProvider
+ DateTimeProvider $dateTimeProvider
) {
$this->application = $applicationFactory->create();
$this->directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
- $this->objectManager = $objectManagerProvider->get();
$this->composerInformation = $composerInformation;
- }
-
- /**
- * Get datetime
- *
- * @return \Magento\Framework\Stdlib\DateTime\DateTime
- */
- private function getDateTime()
- {
- if ($this->dateTime === null) {
- $this->dateTime = $this->objectManager->get('Magento\Setup\Model\DateTime\DateTimeProvider')->get();
- }
- return $this->dateTime;
- }
-
- /**
- * Set datetime
- *
- * @param \Magento\Framework\Stdlib\DateTime\DateTime $dateTime
- * @return void
- * @throws \Exception
- */
- public function setDateTime(\Magento\Framework\Stdlib\DateTime\DateTime $dateTime)
- {
- if ($this->dateTime !== null) {
- throw new \Exception('dateTime is already set');
- }
- $this->dateTime = $dateTime;
+ $this->dateTime = $dateTimeProvider->get();
}
/**
@@ -208,7 +174,7 @@ private function getPackageAvailableVersions($package)
private function savePackagesForUpdateToCache($availableVersions)
{
$syncInfo = [];
- $syncInfo['lastSyncDate'] = $this->getDateTime()->gmtTimestamp();
+ $syncInfo['lastSyncDate'] = $this->dateTime->gmtTimestamp();
$syncInfo['packages'] = $availableVersions;
$data = json_encode($syncInfo, JSON_UNESCAPED_SLASHES);
try {
diff --git a/setup/src/Magento/Setup/Module/Setup.php b/setup/src/Magento/Setup/Module/Setup.php
index 4451267a0e9aa..bac44f28e8d77 100644
--- a/setup/src/Magento/Setup/Module/Setup.php
+++ b/setup/src/Magento/Setup/Module/Setup.php
@@ -19,7 +19,7 @@ class Setup extends \Magento\Framework\Module\Setup implements SchemaSetupInterf
*/
public function getIdxName($tableName, $fields, $indexType = '')
{
- return $this->getConnection()->getIndexName($tableName, $fields, $indexType);
+ return $this->getConnection()->getIndexName($this->getTable($tableName), $fields, $indexType);
}
/**
@@ -33,6 +33,11 @@ public function getIdxName($tableName, $fields, $indexType = '')
*/
public function getFkName($priTableName, $priColumnName, $refTableName, $refColumnName)
{
- return $this->getConnection()->getForeignKeyName($priTableName, $priColumnName, $refTableName, $refColumnName);
+ return $this->getConnection()->getForeignKeyName(
+ $this->getTable($priTableName),
+ $priColumnName,
+ $refTableName,
+ $refColumnName
+ );
}
}
diff --git a/setup/src/Magento/Setup/Test/Unit/Controller/ComponentGridTest.php b/setup/src/Magento/Setup/Test/Unit/Controller/ComponentGridTest.php
index e1501dd01ddf4..9d56a19426e05 100644
--- a/setup/src/Magento/Setup/Test/Unit/Controller/ComponentGridTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Controller/ComponentGridTest.php
@@ -170,9 +170,9 @@ public function setUp()
$this->composerInformationMock,
$objectManagerProvider,
$this->updatePackagesCacheMock,
- $this->marketplaceManagerMock
+ $this->marketplaceManagerMock,
+ $timezoneProviderMock
);
- $this->controller->setTimezone($timezoneProviderMock->get());
}
public function testIndexAction()
diff --git a/setup/src/Magento/Setup/Test/Unit/Controller/SelectVersionTest.php b/setup/src/Magento/Setup/Test/Unit/Controller/SelectVersionTest.php
index 48b73674faff1..3127dd297e488 100644
--- a/setup/src/Magento/Setup/Test/Unit/Controller/SelectVersionTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Controller/SelectVersionTest.php
@@ -67,4 +67,33 @@ public function testSystemPackageActionActionWithError()
$this->assertArrayHasKey('responseType', $variables);
$this->assertEquals(ResponseTypeInterface::RESPONSE_TYPE_ERROR, $variables['responseType']);
}
+
+ public function testInstalledSystemPackageAction()
+ {
+ $this->systemPackage->expects($this->once())
+ ->method('getInstalledSystemPackages')
+ ->willReturn([
+ 'package' => 'magento/product-community-edition',
+ 'versions' => [
+ 'id' => 'magento/product-community-edition',
+ 'name' => 'Version 1.0.0'
+ ]
+ ]);
+ $jsonModel = $this->controller->installedSystemPackageAction();
+ $this->assertInstanceOf('Zend\View\Model\JsonModel', $jsonModel);
+ $variables = $jsonModel->getVariables();
+ $this->assertArrayHasKey('responseType', $variables);
+ $this->assertEquals(ResponseTypeInterface::RESPONSE_TYPE_SUCCESS, $variables['responseType']);
+ }
+
+ public function testInstalledSystemPackageActionWithError()
+ {
+ $this->systemPackage->expects($this->once())
+ ->method('getInstalledSystemPackages')
+ ->will($this->throwException(new \Exception("Test error message")));
+ $jsonModel = $this->controller->installedSystemPackageAction();
+ $variables = $jsonModel->getVariables();
+ $this->assertArrayHasKey('responseType', $variables);
+ $this->assertEquals(ResponseTypeInterface::RESPONSE_TYPE_ERROR, $variables['responseType']);
+ }
}
diff --git a/setup/src/Magento/Setup/Test/Unit/Model/FilePermissionsTest.php b/setup/src/Magento/Setup/Test/Unit/Model/FilePermissionsTest.php
index fe86df12ec117..6e4913f2dd6ef 100644
--- a/setup/src/Magento/Setup/Test/Unit/Model/FilePermissionsTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Model/FilePermissionsTest.php
@@ -6,6 +6,7 @@
namespace Magento\Setup\Test\Unit\Model;
+use Magento\Framework\Filesystem\Driver\File;
use \Magento\Setup\Model\FilePermissions;
use Magento\Framework\App\Filesystem\DirectoryList;
@@ -32,6 +33,11 @@ class FilePermissionsTest extends \PHPUnit_Framework_TestCase
*/
private $filePermissions;
+ /**
+ * @var File
+ */
+ private $driverFileMock;
+
public function setUp()
{
$this->directoryWriteMock = $this->getMock('Magento\Framework\Filesystem\Directory\Write', [], [], '', false);
@@ -43,7 +49,15 @@ public function setUp()
->will($this->returnValue($this->directoryWriteMock));
$this->directoryListMock = $this->getMock('Magento\Framework\App\Filesystem\DirectoryList', [], [], '', false);
- $this->filePermissions = new FilePermissions($this->filesystemMock, $this->directoryListMock);
+ $this->driverFileMock = $this->getMockBuilder(File::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->filePermissions = new FilePermissions(
+ $this->filesystemMock,
+ $this->directoryListMock,
+ $this->driverFileMock
+ );
}
public function testGetInstallationWritableDirectories()
diff --git a/setup/src/Magento/Setup/Test/Unit/Model/SystemPackageTest.php b/setup/src/Magento/Setup/Test/Unit/Model/SystemPackageTest.php
index e78da2dc6cbc1..2f20cb1e284d0 100644
--- a/setup/src/Magento/Setup/Test/Unit/Model/SystemPackageTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Model/SystemPackageTest.php
@@ -177,7 +177,7 @@ public function testGetPackageVersions()
/**
* @expectedException \RuntimeException
- * @expectedExceptionMessage System packages not found
+ * @expectedExceptionMessage We're sorry, no components are available
*/
public function testGetPackageVersionGitCloned()
{
@@ -206,7 +206,7 @@ public function testGetPackageVersionGitCloned()
/**
* @expectedException \RuntimeException
- * @expectedExceptionMessage System package not found
+ * @expectedExceptionMessage We cannot retrieve information on
*/
public function testGetPackageVersionsFailed()
{
diff --git a/setup/src/Magento/Setup/Test/Unit/Module/SetupTest.php b/setup/src/Magento/Setup/Test/Unit/Module/SetupTest.php
index 43c6fc0297ff0..05149673d2551 100644
--- a/setup/src/Magento/Setup/Test/Unit/Module/SetupTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Module/SetupTest.php
@@ -3,11 +3,14 @@
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-
namespace Magento\Setup\Test\Unit\Module;
-use \Magento\Setup\Module\Setup;
+use Magento\Framework\App\ResourceConnection;
+use Magento\Setup\Module\Setup;
+/**
+ * Class SetupTest
+ */
class SetupTest extends \PHPUnit_Framework_TestCase
{
const CONNECTION_NAME = 'connection';
@@ -22,15 +25,20 @@ class SetupTest extends \PHPUnit_Framework_TestCase
*/
private $setup;
+ /**
+ * @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $resourceModelMock;
+
protected function setUp()
{
- $resourceModel = $this->getMock('\Magento\Framework\App\ResourceConnection', [], [], '', false);
+ $this->resourceModelMock = $this->getMock('\Magento\Framework\App\ResourceConnection', [], [], '', false);
$this->connection = $this->getMockForAbstractClass('\Magento\Framework\DB\Adapter\AdapterInterface');
- $resourceModel->expects($this->any())
+ $this->resourceModelMock->expects($this->any())
->method('getConnection')
->with(self::CONNECTION_NAME)
->will($this->returnValue($this->connection));
- $this->setup = new Setup($resourceModel, self::CONNECTION_NAME);
+ $this->setup = new Setup($this->resourceModelMock, self::CONNECTION_NAME);
}
public function testGetIdxName()
@@ -40,6 +48,11 @@ public function testGetIdxName()
$indexType = 'index_type';
$expectedIdxName = 'idxName';
+ $this->resourceModelMock->expects($this->once())
+ ->method('getTableName')
+ ->with($tableName)
+ ->will($this->returnValue($tableName));
+
$this->connection->expects($this->once())
->method('getIndexName')
->with($tableName, $fields, $indexType)
@@ -55,6 +68,11 @@ public function testGetFkName()
$columnName = 'columnName';
$refColumnName = 'refColumnName';
+ $this->resourceModelMock->expects($this->once())
+ ->method('getTableName')
+ ->with($tableName)
+ ->will($this->returnValue($tableName));
+
$this->connection->expects($this->once())
->method('getForeignKeyName')
->with($tableName, $columnName, $refTable, $refColumnName)
diff --git a/setup/view/layout/layout.phtml b/setup/view/layout/layout.phtml
index 274f5e3d366b8..2cc0e6ef3b6b4 100644
--- a/setup/view/layout/layout.phtml
+++ b/setup/view/layout/layout.phtml
@@ -45,6 +45,7 @@
->appendFile($this->basePath() . '/pub/magento/setup/home.js')
->appendFile($this->basePath() . '/pub/magento/setup/auth-dialog.js')
->appendFile($this->basePath() . '/pub/magento/setup/system-config.js')
+ ->appendFile($this->basePath() . '/pub/magento/setup/marketplace-credentials.js')
->appendFile($this->basePath() . '/pub/magento/setup/install-extension-grid.js');
?>
%s
',
'Password Strength:',
- 'Enter a mix of 7 or more numbers and letters. For a stronger password, include at least one small letter, big letter, and symbol (Ex: BuyIt$54).'
+ 'Enter a mix of 7 or more numbers and letters. For a stronger password, include at least one small letter, big letter, and symbol.'
);
?>
diff --git a/setup/view/magento/setup/install-extension-grid.phtml b/setup/view/magento/setup/install-extension-grid.phtml
index a336509285d03..d26a05f72fa7c 100644
--- a/setup/view/magento/setup/install-extension-grid.phtml
+++ b/setup/view/magento/setup/install-extension-grid.phtml
@@ -65,18 +65,18 @@
+ >
+ >
+ >
Options