From ca9e58264092cc56b993f65789e162612a7d5c9e Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Thu, 20 Apr 2017 23:16:22 +0200 Subject: [PATCH 0001/2023] Zend_Feed refactoring progress --- app/code/Magento/Rss/Model/Rss.php | 12 +++- .../Controller/Adminhtml/Feed/IndexTest.php | 19 +++++- .../Test/Unit/Controller/Feed/IndexTest.php | 21 +++++-- app/etc/di.xml | 2 + lib/internal/Magento/Framework/App/Feed.php | 32 ++++++++++ .../Magento/Framework/App/Feed/Importer.php | 58 +++++++++++++++++++ .../Framework/App/FeedImporterInterface.php | 18 ++++++ .../Magento/Framework/App/FeedInterface.php | 14 +++++ .../Exception/FeedImporterException.php | 13 +++++ 9 files changed, 180 insertions(+), 9 deletions(-) create mode 100644 lib/internal/Magento/Framework/App/Feed.php create mode 100644 lib/internal/Magento/Framework/App/Feed/Importer.php create mode 100644 lib/internal/Magento/Framework/App/FeedImporterInterface.php create mode 100644 lib/internal/Magento/Framework/App/FeedInterface.php create mode 100644 lib/internal/Magento/Framework/Exception/FeedImporterException.php diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index 057ebab432aaa..b73db8b1535b1 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -21,6 +21,11 @@ class Rss */ protected $cache; + /** + * @var \Magento\Framework\App\FeedImporterInterface + */ + private $feedImporter; + /** * @var SerializerInterface */ @@ -30,13 +35,16 @@ class Rss * Rss constructor * * @param \Magento\Framework\App\CacheInterface $cache + * @param \Magento\Framework\App\FeedImporterInterface $feedImporter * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\App\CacheInterface $cache, + \Magento\Framework\App\FeedImporterInterface $feedImporter, SerializerInterface $serializer = null ) { $this->cache = $cache; + $this->feedImporter = $feedImporter; $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); } @@ -86,7 +94,7 @@ public function setDataProvider(DataProviderInterface $dataProvider) */ public function createRssXml() { - $rssFeedFromArray = \Zend_Feed::importArray($this->getFeeds(), 'rss'); - return $rssFeedFromArray->saveXML(); + $rssFeed = $this->feedImporter->importArray($this->getFeeds(), 'rss'); + return $rssFeed->asXML(); } } diff --git a/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php b/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php index 0495212cfba71..209f393212af1 100644 --- a/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php +++ b/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php @@ -102,15 +102,28 @@ public function testExecuteWithException() $this->scopeConfigInterface->expects($this->once())->method('getValue')->will($this->returnValue(true)); $dataProvider = $this->getMock(\Magento\Framework\App\Rss\DataProviderInterface::class); $dataProvider->expects($this->once())->method('isAllowed')->will($this->returnValue(true)); + $dataProvider->expects($this->once())->method('getRssData')->will($this->returnValue([])); - $rssModel = $this->getMock(\Magento\Rss\Model\Rss::class, ['setDataProvider'], [], '', false); - $rssModel->expects($this->once())->method('setDataProvider')->will($this->returnSelf()); + $objectManagerHelper = new ObjectManagerHelper($this); + $feedImporter = $objectManagerHelper->getObject( + \Magento\Framework\App\Feed\Importer::class, + [ + 'feedProcessor' => $objectManagerHelper->getObject(\Zend_Feed::class), + ] + ); + + $rssModel = $objectManagerHelper->getObject( + \Magento\Rss\Model\Rss::class, + [ + 'feedImporter' => $feedImporter, + ] + ); $this->response->expects($this->once())->method('setHeader')->will($this->returnSelf()); $this->rssFactory->expects($this->once())->method('create')->will($this->returnValue($rssModel)); $this->rssManager->expects($this->once())->method('getProvider')->will($this->returnValue($dataProvider)); - $this->setExpectedException('\Zend_Feed_Builder_Exception'); + $this->setExpectedException('\Magento\Framework\Exception\FeedImporterException'); $this->controller->execute(); } } diff --git a/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php b/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php index a8ca05af3a68d..21ae5ec6822df 100644 --- a/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php +++ b/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php @@ -52,6 +52,7 @@ protected function setUp() ->disableOriginalConstructor()->getMock(); $objectManagerHelper = new ObjectManagerHelper($this); + $this->controller = $objectManagerHelper->getObject( \Magento\Rss\Controller\Feed\Index::class, [ @@ -89,15 +90,27 @@ public function testExecuteWithException() $this->scopeConfigInterface->expects($this->once())->method('getValue')->will($this->returnValue(true)); $dataProvider = $this->getMock(\Magento\Framework\App\Rss\DataProviderInterface::class); $dataProvider->expects($this->once())->method('isAllowed')->will($this->returnValue(true)); - - $rssModel = $this->getMock(\Magento\Rss\Model\Rss::class, ['setDataProvider'], [], '', false); - $rssModel->expects($this->once())->method('setDataProvider')->will($this->returnSelf()); + $dataProvider->expects($this->once())->method('getRssData')->will($this->returnValue([])); + + $objectManagerHelper = new ObjectManagerHelper($this); + $feedImporter = $objectManagerHelper->getObject( + \Magento\Framework\App\Feed\Importer::class, + [ + 'feedProcessor' => $objectManagerHelper->getObject(\Zend_Feed::class), + ] + ); + $rssModel = $objectManagerHelper->getObject( + \Magento\Rss\Model\Rss::class, + [ + 'feedImporter' => $feedImporter, + ] + ); $this->response->expects($this->once())->method('setHeader')->will($this->returnSelf()); $this->rssFactory->expects($this->once())->method('create')->will($this->returnValue($rssModel)); $this->rssManager->expects($this->once())->method('getProvider')->will($this->returnValue($dataProvider)); - $this->setExpectedException('\Zend_Feed_Builder_Exception'); + $this->setExpectedException('\Magento\Framework\Exception\FeedImporterException'); $this->controller->execute(); } } diff --git a/app/etc/di.xml b/app/etc/di.xml index 91c008219992e..3643588dbbf25 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -170,6 +170,8 @@ + + diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php new file mode 100644 index 0000000000000..9c976c807a750 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -0,0 +1,32 @@ +feed = $feed; + } + + /** + * Get the xml from Zend_Feed_Abstract object + * + * @return string + */ + public function asXml() + { + return $this->feed->saveXml(); + } +} diff --git a/lib/internal/Magento/Framework/App/Feed/Importer.php b/lib/internal/Magento/Framework/App/Feed/Importer.php new file mode 100644 index 0000000000000..fed94df5751c1 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Feed/Importer.php @@ -0,0 +1,58 @@ +feedProcessor = $feedProcessor; + $this->feedFactory = $feedFactory; + } + + /** + * Get a new \Magento\Framework\App\Feed object from a custom array + * + * @throws \Magento\Framework\Exception\FeedImporterException + * @param array $data + * @param string $format + * @return \Magento\Framework\App\FeedInterface + */ + public function importArray(array $data, $format = 'atom') + { + try { + $feed = $this->feedProcessor->importArray($data, $format); + return $this->feedFactory->create(['feed' => $feed]); + } + catch (\Zend_Feed_Exception $e) { + throw new \Magento\Framework\Exception\FeedImporterException( + new \Magento\Framework\Phrase($e->getMessage()), + $e + ); + } + } +} + + diff --git a/lib/internal/Magento/Framework/App/FeedImporterInterface.php b/lib/internal/Magento/Framework/App/FeedImporterInterface.php new file mode 100644 index 0000000000000..6f276c0caa7dd --- /dev/null +++ b/lib/internal/Magento/Framework/App/FeedImporterInterface.php @@ -0,0 +1,18 @@ + Date: Fri, 21 Apr 2017 16:11:39 +0200 Subject: [PATCH 0002/2023] Tests refactoring --- .../Controller/Adminhtml/Feed/IndexTest.php | 19 ++++++--------- .../Test/Unit/Controller/Feed/IndexTest.php | 24 ++++++++----------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php b/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php index 209f393212af1..b9c6a80fc4deb 100644 --- a/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php +++ b/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php @@ -102,21 +102,16 @@ public function testExecuteWithException() $this->scopeConfigInterface->expects($this->once())->method('getValue')->will($this->returnValue(true)); $dataProvider = $this->getMock(\Magento\Framework\App\Rss\DataProviderInterface::class); $dataProvider->expects($this->once())->method('isAllowed')->will($this->returnValue(true)); - $dataProvider->expects($this->once())->method('getRssData')->will($this->returnValue([])); - $objectManagerHelper = new ObjectManagerHelper($this); - $feedImporter = $objectManagerHelper->getObject( - \Magento\Framework\App\Feed\Importer::class, - [ - 'feedProcessor' => $objectManagerHelper->getObject(\Zend_Feed::class), - ] + $rssModel = $this->getMock(\Magento\Rss\Model\Rss::class, ['setDataProvider', 'createRssXml'], [], '', false); + $rssModel->expects($this->once())->method('setDataProvider')->will($this->returnSelf()); + + $exceptionMock = new \Magento\Framework\Exception\FeedImporterException( + new \Magento\Framework\Phrase('Any message') ); - $rssModel = $objectManagerHelper->getObject( - \Magento\Rss\Model\Rss::class, - [ - 'feedImporter' => $feedImporter, - ] + $rssModel->expects($this->once())->method('createRssXml')->will( + $this->throwException($exceptionMock) ); $this->response->expects($this->once())->method('setHeader')->will($this->returnSelf()); diff --git a/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php b/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php index 21ae5ec6822df..2cf23c9d29edd 100644 --- a/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php +++ b/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php @@ -90,27 +90,23 @@ public function testExecuteWithException() $this->scopeConfigInterface->expects($this->once())->method('getValue')->will($this->returnValue(true)); $dataProvider = $this->getMock(\Magento\Framework\App\Rss\DataProviderInterface::class); $dataProvider->expects($this->once())->method('isAllowed')->will($this->returnValue(true)); - $dataProvider->expects($this->once())->method('getRssData')->will($this->returnValue([])); - - $objectManagerHelper = new ObjectManagerHelper($this); - $feedImporter = $objectManagerHelper->getObject( - \Magento\Framework\App\Feed\Importer::class, - [ - 'feedProcessor' => $objectManagerHelper->getObject(\Zend_Feed::class), - ] + + $rssModel = $this->getMock(\Magento\Rss\Model\Rss::class, ['setDataProvider', 'createRssXml'], [], '', false); + $rssModel->expects($this->once())->method('setDataProvider')->will($this->returnSelf()); + + $exceptionMock = new \Magento\Framework\Exception\FeedImporterException( + new \Magento\Framework\Phrase('Any message') ); - $rssModel = $objectManagerHelper->getObject( - \Magento\Rss\Model\Rss::class, - [ - 'feedImporter' => $feedImporter, - ] + + $rssModel->expects($this->once())->method('createRssXml')->will( + $this->throwException($exceptionMock) ); $this->response->expects($this->once())->method('setHeader')->will($this->returnSelf()); $this->rssFactory->expects($this->once())->method('create')->will($this->returnValue($rssModel)); $this->rssManager->expects($this->once())->method('getProvider')->will($this->returnValue($dataProvider)); - $this->setExpectedException('\Magento\Framework\Exception\FeedImporterException'); + $this->setExpectedException(\Magento\Framework\Exception\FeedImporterException::class); $this->controller->execute(); } } From c7ba65a1caeabbbde4a32fa57938811255f34715 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Sat, 22 Apr 2017 13:32:40 +0200 Subject: [PATCH 0003/2023] Fixed unit test --- .../Magento/Rss/Test/Unit/Model/RssTest.php | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php index 7674aedf2d3f6..6b5d5e2eab4b5 100644 --- a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php +++ b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php @@ -33,6 +33,27 @@ class RssTest extends \PHPUnit_Framework_TestCase ], ]; + /** + * @var string + */ + protected $feedXml = ' + + + <![CDATA[Feed Title]]> + http://magento.com/rss/link + + Sat, 22 Apr 2017 13:21:12 +0200 + Zend_Feed + http://blogs.law.harvard.edu/tech/rss + + <![CDATA[Feed 1 Title]]> + http://magento.com/rss/link/id/1 + + Sat, 22 Apr 2017 13:21:12 +0200 + + +'; + /** * @var ObjectManagerHelper */ @@ -43,6 +64,16 @@ class RssTest extends \PHPUnit_Framework_TestCase */ private $cacheMock; + /** + * @var \Magento\Framework\App\FeedImporterInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $feedImporterMock; + + /** + * @var \Magento\Framework\App\FeedInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $feedMock; + /** * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ @@ -52,11 +83,15 @@ protected function setUp() { $this->cacheMock = $this->getMock(\Magento\Framework\App\CacheInterface::class); $this->serializerMock = $this->getMock(SerializerInterface::class); + $this->feedImporterMock = $this->getMock(\Magento\Framework\App\FeedImporterInterface::class); + $this->feedMock = $this->getMock(\Magento\Framework\App\FeedInterface::class); + $this->objectManagerHelper = new ObjectManagerHelper($this); $this->rss = $this->objectManagerHelper->getObject( \Magento\Rss\Model\Rss::class, [ 'cache' => $this->cacheMock, + 'feedImporter' => $this->feedImporterMock, 'serializer' => $this->serializerMock ] ); @@ -116,6 +151,15 @@ public function testCreateRssXml() $dataProvider->expects($this->any())->method('getCacheLifetime')->will($this->returnValue(100)); $dataProvider->expects($this->any())->method('getRssData')->will($this->returnValue($this->feedData)); + $this->feedMock->expects($this->once()) + ->method('asXml') + ->will($this->returnValue($this->feedXml)); + + $this->feedImporterMock->expects($this->once()) + ->method('importArray') + ->with($this->feedData) + ->will($this->returnValue($this->feedMock)); + $this->rss->setDataProvider($dataProvider); $result = $this->rss->createRssXml(); $this->assertContains('', $result); From 9d0a290457df41971334906108e976b55c003651 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Sat, 22 Apr 2017 13:33:40 +0200 Subject: [PATCH 0004/2023] Tidying up files --- .../Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php | 2 +- lib/internal/Magento/Framework/App/Feed.php | 4 ++-- lib/internal/Magento/Framework/App/Feed/Importer.php | 8 +++----- .../Magento/Framework/Exception/FeedImporterException.php | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php b/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php index b9c6a80fc4deb..790ca898d0290 100644 --- a/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php +++ b/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php @@ -118,7 +118,7 @@ public function testExecuteWithException() $this->rssFactory->expects($this->once())->method('create')->will($this->returnValue($rssModel)); $this->rssManager->expects($this->once())->method('getProvider')->will($this->returnValue($dataProvider)); - $this->setExpectedException('\Magento\Framework\Exception\FeedImporterException'); + $this->setExpectedException(\Magento\Framework\Exception\FeedImporterException::class); $this->controller->execute(); } } diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 9c976c807a750..e9bccf4c9ed78 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -15,7 +15,7 @@ class Feed implements \Magento\Framework\App\FeedInterface /** * @param \Zend_Feed_Abstract $feed */ - public function __construct(\Zend_Feed_Abstract $feed) + public function __construct(\Zend_Feed_Abstract $feed) { $this->feed = $feed; } @@ -29,4 +29,4 @@ public function asXml() { return $this->feed->saveXml(); } -} +} \ No newline at end of file diff --git a/lib/internal/Magento/Framework/App/Feed/Importer.php b/lib/internal/Magento/Framework/App/Feed/Importer.php index fed94df5751c1..42bbc90267588 100644 --- a/lib/internal/Magento/Framework/App/Feed/Importer.php +++ b/lib/internal/Magento/Framework/App/Feed/Importer.php @@ -42,11 +42,11 @@ public function __construct( */ public function importArray(array $data, $format = 'atom') { + try { $feed = $this->feedProcessor->importArray($data, $format); - return $this->feedFactory->create(['feed' => $feed]); - } - catch (\Zend_Feed_Exception $e) { + return $this->feedFactory->create(['feed' => $feed]); + } catch (\Zend_Feed_Exception $e) { throw new \Magento\Framework\Exception\FeedImporterException( new \Magento\Framework\Phrase($e->getMessage()), $e @@ -54,5 +54,3 @@ public function importArray(array $data, $format = 'atom') } } } - - diff --git a/lib/internal/Magento/Framework/Exception/FeedImporterException.php b/lib/internal/Magento/Framework/Exception/FeedImporterException.php index 0a197e6bc2ab2..e6faec0a60270 100644 --- a/lib/internal/Magento/Framework/Exception/FeedImporterException.php +++ b/lib/internal/Magento/Framework/Exception/FeedImporterException.php @@ -10,4 +10,4 @@ class FeedImporterException extends LocalizedException { -} \ No newline at end of file +} From 109047fa18803a3922b0572a0aa21e6b14e9a9de Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Sat, 22 Apr 2017 14:07:57 +0200 Subject: [PATCH 0005/2023] Small CS fix --- lib/internal/Magento/Framework/App/Feed.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index e9bccf4c9ed78..044b5c68c516c 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -29,4 +29,5 @@ public function asXml() { return $this->feed->saveXml(); } -} \ No newline at end of file +} + From 4534a2e41f487352b2413d94ab825f2414eba7a7 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Sat, 22 Apr 2017 14:49:57 +0200 Subject: [PATCH 0006/2023] Small CS fix --- lib/internal/Magento/Framework/App/Feed.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 044b5c68c516c..2fab3da33173e 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -30,4 +30,3 @@ public function asXml() return $this->feed->saveXml(); } } - From c413389ffe73799d8faebbece88208c39cdf0f5c Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Sat, 29 Apr 2017 18:36:48 +0200 Subject: [PATCH 0007/2023] More CS fixes --- app/code/Magento/Rss/Test/Unit/Model/RssTest.php | 2 +- lib/internal/Magento/Framework/App/Feed.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php index 6b5d5e2eab4b5..f922a936a9add 100644 --- a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php +++ b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php @@ -85,7 +85,7 @@ protected function setUp() $this->serializerMock = $this->getMock(SerializerInterface::class); $this->feedImporterMock = $this->getMock(\Magento\Framework\App\FeedImporterInterface::class); $this->feedMock = $this->getMock(\Magento\Framework\App\FeedInterface::class); - + $this->objectManagerHelper = new ObjectManagerHelper($this); $this->rss = $this->objectManagerHelper->getObject( \Magento\Rss\Model\Rss::class, diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 2fab3da33173e..1a8fe94db4b1b 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -22,7 +22,7 @@ public function __construct(\Zend_Feed_Abstract $feed) /** * Get the xml from Zend_Feed_Abstract object - * + * * @return string */ public function asXml() From caa4471aede4e4415fe4abb629f28c8e0ef6d954 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Sun, 7 May 2017 15:16:31 +0200 Subject: [PATCH 0008/2023] Small exception fix --- lib/internal/Magento/Framework/App/Feed/Importer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/Feed/Importer.php b/lib/internal/Magento/Framework/App/Feed/Importer.php index 42bbc90267588..20fd1e051fde4 100644 --- a/lib/internal/Magento/Framework/App/Feed/Importer.php +++ b/lib/internal/Magento/Framework/App/Feed/Importer.php @@ -48,7 +48,7 @@ public function importArray(array $data, $format = 'atom') return $this->feedFactory->create(['feed' => $feed]); } catch (\Zend_Feed_Exception $e) { throw new \Magento\Framework\Exception\FeedImporterException( - new \Magento\Framework\Phrase($e->getMessage()), + __($e->getMessage()), $e ); } From 66154e6e95807650591a7ad8b6e049ddd883b919 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Wed, 24 May 2017 17:26:35 +0200 Subject: [PATCH 0009/2023] Changes after the code review --- app/code/Magento/Rss/Model/Rss.php | 9 +++---- .../Controller/Adminhtml/Feed/IndexTest.php | 4 ++-- .../Test/Unit/Controller/Feed/IndexTest.php | 4 ++-- .../Magento/Rss/Test/Unit/Model/RssTest.php | 4 ++-- .../Magento/Framework/App/Feed/Importer.php | 24 ++++++++++++++----- .../Framework/App/FeedImporterInterface.php | 4 +++- .../Exception/FeedImporterException.php | 13 ---------- 7 files changed, 32 insertions(+), 30 deletions(-) delete mode 100644 lib/internal/Magento/Framework/Exception/FeedImporterException.php diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index b73db8b1535b1..d90b5accbbdf9 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -8,6 +8,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Rss\DataProviderInterface; use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\App\FeedImporterInterface; class Rss { @@ -35,17 +36,17 @@ class Rss * Rss constructor * * @param \Magento\Framework\App\CacheInterface $cache - * @param \Magento\Framework\App\FeedImporterInterface $feedImporter * @param SerializerInterface|null $serializer + * @param FeedImporterInterface|null $feedImporter */ public function __construct( \Magento\Framework\App\CacheInterface $cache, - \Magento\Framework\App\FeedImporterInterface $feedImporter, - SerializerInterface $serializer = null + SerializerInterface $serializer = null, + FeedImporterInterface $feedImporter = null ) { $this->cache = $cache; - $this->feedImporter = $feedImporter; $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); + $this->feedImporter = $feedImporter ?: ObjectManager::getInstance()->get(FeedImporterInterface::class); } /** diff --git a/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php b/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php index 790ca898d0290..b11a1d8f63971 100644 --- a/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php +++ b/app/code/Magento/Rss/Test/Unit/Controller/Adminhtml/Feed/IndexTest.php @@ -106,7 +106,7 @@ public function testExecuteWithException() $rssModel = $this->getMock(\Magento\Rss\Model\Rss::class, ['setDataProvider', 'createRssXml'], [], '', false); $rssModel->expects($this->once())->method('setDataProvider')->will($this->returnSelf()); - $exceptionMock = new \Magento\Framework\Exception\FeedImporterException( + $exceptionMock = new \Magento\Framework\Exception\RuntimeException( new \Magento\Framework\Phrase('Any message') ); @@ -118,7 +118,7 @@ public function testExecuteWithException() $this->rssFactory->expects($this->once())->method('create')->will($this->returnValue($rssModel)); $this->rssManager->expects($this->once())->method('getProvider')->will($this->returnValue($dataProvider)); - $this->setExpectedException(\Magento\Framework\Exception\FeedImporterException::class); + $this->setExpectedException(\Magento\Framework\Exception\RuntimeException::class); $this->controller->execute(); } } diff --git a/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php b/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php index 2cf23c9d29edd..c8186b6b49427 100644 --- a/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php +++ b/app/code/Magento/Rss/Test/Unit/Controller/Feed/IndexTest.php @@ -94,7 +94,7 @@ public function testExecuteWithException() $rssModel = $this->getMock(\Magento\Rss\Model\Rss::class, ['setDataProvider', 'createRssXml'], [], '', false); $rssModel->expects($this->once())->method('setDataProvider')->will($this->returnSelf()); - $exceptionMock = new \Magento\Framework\Exception\FeedImporterException( + $exceptionMock = new \Magento\Framework\Exception\RuntimeException( new \Magento\Framework\Phrase('Any message') ); @@ -106,7 +106,7 @@ public function testExecuteWithException() $this->rssFactory->expects($this->once())->method('create')->will($this->returnValue($rssModel)); $this->rssManager->expects($this->once())->method('getProvider')->will($this->returnValue($dataProvider)); - $this->setExpectedException(\Magento\Framework\Exception\FeedImporterException::class); + $this->setExpectedException(\Magento\Framework\Exception\RuntimeException::class); $this->controller->execute(); } } diff --git a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php index f922a936a9add..f84ded89cdfce 100644 --- a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php +++ b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php @@ -19,7 +19,7 @@ class RssTest extends \PHPUnit_Framework_TestCase /** * @var array */ - protected $feedData = [ + private $feedData = [ 'title' => 'Feed Title', 'link' => 'http://magento.com/rss/link', 'description' => 'Feed Description', @@ -36,7 +36,7 @@ class RssTest extends \PHPUnit_Framework_TestCase /** * @var string */ - protected $feedXml = ' + private $feedXml = ' <![CDATA[Feed Title]]> diff --git a/lib/internal/Magento/Framework/App/Feed/Importer.php b/lib/internal/Magento/Framework/App/Feed/Importer.php index 20fd1e051fde4..e0e1ba13ab1e6 100644 --- a/lib/internal/Magento/Framework/App/Feed/Importer.php +++ b/lib/internal/Magento/Framework/App/Feed/Importer.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\App\Feed; +use Magento\Framework\App\FeedFactory; +use Psr\Log\LoggerInterface; + /** * Feed importer */ @@ -16,26 +19,34 @@ class Importer implements \Magento\Framework\App\FeedImporterInterface private $feedProcessor; /** - * @var \Magento\Framework\App\FeedFactory + * @var FeedFactory */ private $feedFactory; + /** + * @var LoggerInterface + */ + private $logger; + /** * @param \Zend_Feed $feedProcessor - * @param \Magento\Framework\App\FeedFactory $feedFactory + * @param FeedFactory $feedFactory + * @param LoggerInterface $logger */ public function __construct( \Zend_Feed $feedProcessor, - \Magento\Framework\App\FeedFactory $feedFactory + FeedFactory $feedFactory, + LoggerInterface $logger ) { $this->feedProcessor = $feedProcessor; $this->feedFactory = $feedFactory; + $this->logger = $logger; } /** * Get a new \Magento\Framework\App\Feed object from a custom array * - * @throws \Magento\Framework\Exception\FeedImporterException + * @throws \Magento\Framework\Exception\RuntimeException * @param array $data * @param string $format * @return \Magento\Framework\App\FeedInterface @@ -47,8 +58,9 @@ public function importArray(array $data, $format = 'atom') $feed = $this->feedProcessor->importArray($data, $format); return $this->feedFactory->create(['feed' => $feed]); } catch (\Zend_Feed_Exception $e) { - throw new \Magento\Framework\Exception\FeedImporterException( - __($e->getMessage()), + $this->logger->error($e->getMessage()); + throw new \Magento\Framework\Exception\RuntimeException( + __('There has been an error with import'), $e ); } diff --git a/lib/internal/Magento/Framework/App/FeedImporterInterface.php b/lib/internal/Magento/Framework/App/FeedImporterInterface.php index 6f276c0caa7dd..cd99b1257b93a 100644 --- a/lib/internal/Magento/Framework/App/FeedImporterInterface.php +++ b/lib/internal/Magento/Framework/App/FeedImporterInterface.php @@ -9,7 +9,9 @@ interface FeedImporterInterface { /** - * @throws \Magento\Framework\Exception\FeedImporterException + * Returns FeedInterface object from a custom array + * + * @throws \Magento\Framework\Exception\RuntimeException * @param array $data * @param string $format * @return FeedInterface diff --git a/lib/internal/Magento/Framework/Exception/FeedImporterException.php b/lib/internal/Magento/Framework/Exception/FeedImporterException.php deleted file mode 100644 index e6faec0a60270..0000000000000 --- a/lib/internal/Magento/Framework/Exception/FeedImporterException.php +++ /dev/null @@ -1,13 +0,0 @@ - Date: Thu, 27 Jul 2017 14:23:10 +0200 Subject: [PATCH 0010/2023] Zend Feed refactorging WIP --- .../App/{Feed/Importer.php => FeedFactory.php} | 15 +++------------ ...rterInterface.php => FeedFactoryInterface.php} | 7 +++++-- .../Framework/App/FeedFormatsInterface.php | 11 +++++++++++ 3 files changed, 19 insertions(+), 14 deletions(-) rename lib/internal/Magento/Framework/App/{Feed/Importer.php => FeedFactory.php} (74%) rename lib/internal/Magento/Framework/App/{FeedImporterInterface.php => FeedFactoryInterface.php} (71%) create mode 100644 lib/internal/Magento/Framework/App/FeedFormatsInterface.php diff --git a/lib/internal/Magento/Framework/App/Feed/Importer.php b/lib/internal/Magento/Framework/App/FeedFactory.php similarity index 74% rename from lib/internal/Magento/Framework/App/Feed/Importer.php rename to lib/internal/Magento/Framework/App/FeedFactory.php index e0e1ba13ab1e6..978462e4abdc3 100644 --- a/lib/internal/Magento/Framework/App/Feed/Importer.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Framework\App\Feed; +namespace Magento\Framework\App; use Magento\Framework\App\FeedFactory; use Psr\Log\LoggerInterface; @@ -11,18 +11,13 @@ /** * Feed importer */ -class Importer implements \Magento\Framework\App\FeedImporterInterface +class FeedFactory implements \Magento\Framework\App\FeedImporterInterface { /** * @var \Zend_Feed */ private $feedProcessor; - /** - * @var FeedFactory - */ - private $feedFactory; - /** * @var LoggerInterface */ @@ -30,16 +25,13 @@ class Importer implements \Magento\Framework\App\FeedImporterInterface /** * @param \Zend_Feed $feedProcessor - * @param FeedFactory $feedFactory * @param LoggerInterface $logger */ public function __construct( \Zend_Feed $feedProcessor, - FeedFactory $feedFactory, LoggerInterface $logger ) { $this->feedProcessor = $feedProcessor; - $this->feedFactory = $feedFactory; $this->logger = $logger; } @@ -55,8 +47,7 @@ public function importArray(array $data, $format = 'atom') { try { - $feed = $this->feedProcessor->importArray($data, $format); - return $this->feedFactory->create(['feed' => $feed]); + return $this->feedProcessor->importArray($data, $format); } catch (\Zend_Feed_Exception $e) { $this->logger->error($e->getMessage()); throw new \Magento\Framework\Exception\RuntimeException( diff --git a/lib/internal/Magento/Framework/App/FeedImporterInterface.php b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php similarity index 71% rename from lib/internal/Magento/Framework/App/FeedImporterInterface.php rename to lib/internal/Magento/Framework/App/FeedFactoryInterface.php index cd99b1257b93a..5147fccd638a7 100644 --- a/lib/internal/Magento/Framework/App/FeedImporterInterface.php +++ b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php @@ -5,7 +5,7 @@ */ namespace Magento\Framework\App; -interface FeedImporterInterface +interface FeedFactoryInterface { /** @@ -16,5 +16,8 @@ interface FeedImporterInterface * @param string $format * @return FeedInterface */ - public function importArray(array $data, $format = 'atom'); + public function importArray( + array $data, + $format = FeedFormatsInterface::DEFAULT_FORMAT + ); } diff --git a/lib/internal/Magento/Framework/App/FeedFormatsInterface.php b/lib/internal/Magento/Framework/App/FeedFormatsInterface.php new file mode 100644 index 0000000000000..e7610e09f5684 --- /dev/null +++ b/lib/internal/Magento/Framework/App/FeedFormatsInterface.php @@ -0,0 +1,11 @@ + Date: Mon, 7 Aug 2017 15:43:26 -0700 Subject: [PATCH 0011/2023] Implementing code review requested changes --- app/code/Magento/Rss/Model/Rss.php | 22 ++++++++++++------- .../Magento/Rss/Test/Unit/Model/RssTest.php | 15 +++++++------ app/etc/di.xml | 2 +- lib/internal/Magento/Framework/App/Feed.php | 15 +++++++++---- .../Magento/Framework/App/FeedFactory.php | 7 +++--- .../Framework/App/FeedFormatsInterface.php | 2 +- .../Magento/Framework/App/FeedInterface.php | 4 +++- .../App/FeedOutputFormatsInterface.php | 11 ++++++++++ 8 files changed, 52 insertions(+), 26 deletions(-) create mode 100644 lib/internal/Magento/Framework/App/FeedOutputFormatsInterface.php diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index d90b5accbbdf9..85cf459bdc75f 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -8,7 +8,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Rss\DataProviderInterface; use Magento\Framework\Serialize\SerializerInterface; -use Magento\Framework\App\FeedImporterInterface; +use Magento\Framework\App\FeedFactoryInterface; class Rss { @@ -23,9 +23,9 @@ class Rss protected $cache; /** - * @var \Magento\Framework\App\FeedImporterInterface + * @var \Magento\Framework\App\FeedFactoryInterface */ - private $feedImporter; + private $feedFactory; /** * @var SerializerInterface @@ -37,16 +37,16 @@ class Rss * * @param \Magento\Framework\App\CacheInterface $cache * @param SerializerInterface|null $serializer - * @param FeedImporterInterface|null $feedImporter + * @param FeedFactoryInterface|null $feedFactory */ public function __construct( \Magento\Framework\App\CacheInterface $cache, SerializerInterface $serializer = null, - FeedImporterInterface $feedImporter = null + FeedFactoryInterface $feedFactory = null ) { $this->cache = $cache; $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); - $this->feedImporter = $feedImporter ?: ObjectManager::getInstance()->get(FeedImporterInterface::class); + $this->feedFactory = $feedFactory ?: ObjectManager::getInstance()->get(FeedFactoryInterface::class); } /** @@ -95,7 +95,13 @@ public function setDataProvider(DataProviderInterface $dataProvider) */ public function createRssXml() { - $rssFeed = $this->feedImporter->importArray($this->getFeeds(), 'rss'); - return $rssFeed->asXML(); + $feed = $this->feedFactory->importArray( + $this->getFeeds(), + \Magento\Framework\App\FeedFormatsInterface::DEFAULT_FORMAT + ); + + return $feed->getFormatedContentAs( + \Magento\Framework\App\FeedOutputFormatsInterface::DEFAULT_FORMAT + ); } } diff --git a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php index f84ded89cdfce..68d15a20a7428 100644 --- a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php +++ b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php @@ -65,9 +65,9 @@ class RssTest extends \PHPUnit_Framework_TestCase private $cacheMock; /** - * @var \Magento\Framework\App\FeedImporterInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\FeedFactoryInterface|\PHPUnit_Framework_MockObject_MockObject */ - private $feedImporterMock; + private $feedFactoryMock; /** * @var \Magento\Framework\App\FeedInterface|\PHPUnit_Framework_MockObject_MockObject @@ -83,7 +83,7 @@ protected function setUp() { $this->cacheMock = $this->getMock(\Magento\Framework\App\CacheInterface::class); $this->serializerMock = $this->getMock(SerializerInterface::class); - $this->feedImporterMock = $this->getMock(\Magento\Framework\App\FeedImporterInterface::class); + $this->feedFactoryMock = $this->getMock(\Magento\Framework\App\FeedFactoryInterface::class); $this->feedMock = $this->getMock(\Magento\Framework\App\FeedInterface::class); $this->objectManagerHelper = new ObjectManagerHelper($this); @@ -91,7 +91,7 @@ protected function setUp() \Magento\Rss\Model\Rss::class, [ 'cache' => $this->cacheMock, - 'feedImporter' => $this->feedImporterMock, + 'feedFactory' => $this->feedFactoryMock, 'serializer' => $this->serializerMock ] ); @@ -152,12 +152,13 @@ public function testCreateRssXml() $dataProvider->expects($this->any())->method('getRssData')->will($this->returnValue($this->feedData)); $this->feedMock->expects($this->once()) - ->method('asXml') + ->method('getFormatedContentAs') + ->with(\Magento\Framework\App\FeedOutputFormatsInterface::DEFAULT_FORMAT) ->will($this->returnValue($this->feedXml)); - $this->feedImporterMock->expects($this->once()) + $this->feedFactoryMock->expects($this->once()) ->method('importArray') - ->with($this->feedData) + ->with($this->feedData, \Magento\Framework\App\FeedFormatsInterface::DEFAULT_FORMAT) ->will($this->returnValue($this->feedMock)); $this->rss->setDataProvider($dataProvider); diff --git a/app/etc/di.xml b/app/etc/di.xml index 3643588dbbf25..ffdd76bab1bf6 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -171,7 +171,7 @@ - + diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 1a8fe94db4b1b..018b7c295d76d 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -8,7 +8,7 @@ class Feed implements \Magento\Framework\App\FeedInterface { /** - * @var \Magento\Framework\App\FeedImporterInterface + * @var \Zend_Feed_Abstract */ private $feed; @@ -25,8 +25,15 @@ public function __construct(\Zend_Feed_Abstract $feed) * * @return string */ - public function asXml() - { - return $this->feed->saveXml(); + public function getFormatedContentAs( + $format = FeedOutputFormatsInterface::DEFAULT_FORMAT + ) { + if ($format === FeedOutputFormatsInterface::DEFAULT_FORMAT) { + return $this->feed->saveXml(); + } + throw new \Magento\Framework\Exception\RuntimeException( + __('Given feed format is not supported'), + $e + ); } } diff --git a/lib/internal/Magento/Framework/App/FeedFactory.php b/lib/internal/Magento/Framework/App/FeedFactory.php index 978462e4abdc3..f198b4ad90f0f 100644 --- a/lib/internal/Magento/Framework/App/FeedFactory.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -9,9 +9,9 @@ use Psr\Log\LoggerInterface; /** - * Feed importer + * Feed factory */ -class FeedFactory implements \Magento\Framework\App\FeedImporterInterface +class FeedFactory implements \Magento\Framework\App\FeedFactoryInterface { /** * @var \Zend_Feed @@ -43,9 +43,8 @@ public function __construct( * @param string $format * @return \Magento\Framework\App\FeedInterface */ - public function importArray(array $data, $format = 'atom') + public function importArray(array $data, $format = FeedFormatsInterface::DEFAULT_FORMAT) { - try { return $this->feedProcessor->importArray($data, $format); } catch (\Zend_Feed_Exception $e) { diff --git a/lib/internal/Magento/Framework/App/FeedFormatsInterface.php b/lib/internal/Magento/Framework/App/FeedFormatsInterface.php index e7610e09f5684..027a89f7a47d2 100644 --- a/lib/internal/Magento/Framework/App/FeedFormatsInterface.php +++ b/lib/internal/Magento/Framework/App/FeedFormatsInterface.php @@ -7,5 +7,5 @@ interface FeedFormatsInterface { - const DEFAULT_FORMAT = 'atom'; + const DEFAULT_FORMAT = 'rss'; } \ No newline at end of file diff --git a/lib/internal/Magento/Framework/App/FeedInterface.php b/lib/internal/Magento/Framework/App/FeedInterface.php index 2c3c3ce431920..b8d792f4644d4 100644 --- a/lib/internal/Magento/Framework/App/FeedInterface.php +++ b/lib/internal/Magento/Framework/App/FeedInterface.php @@ -10,5 +10,7 @@ interface FeedInterface /** * @return string */ - public function asXml(); + public function getFormatedContentAs( + $format = FeedOutputFormatsInterface::DEFAULT_FORMAT + ); } diff --git a/lib/internal/Magento/Framework/App/FeedOutputFormatsInterface.php b/lib/internal/Magento/Framework/App/FeedOutputFormatsInterface.php new file mode 100644 index 0000000000000..e33348a88d551 --- /dev/null +++ b/lib/internal/Magento/Framework/App/FeedOutputFormatsInterface.php @@ -0,0 +1,11 @@ + Date: Mon, 4 Sep 2017 16:49:48 +0200 Subject: [PATCH 0012/2023] Zend Feed refactoring WIP --- lib/internal/Magento/Framework/App/Feed.php | 6 ++++-- lib/internal/Magento/Framework/App/FeedFactory.php | 13 ++++++++----- .../Magento/Framework/App/FeedFactoryInterface.php | 6 ++++-- .../Magento/Framework/App/FeedFormatsInterface.php | 11 ----------- .../Magento/Framework/App/FeedInterface.php | 4 +++- .../Framework/App/FeedOutputFormatsInterface.php | 11 ----------- 6 files changed, 19 insertions(+), 32 deletions(-) delete mode 100644 lib/internal/Magento/Framework/App/FeedFormatsInterface.php delete mode 100644 lib/internal/Magento/Framework/App/FeedOutputFormatsInterface.php diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 018b7c295d76d..8df5b63a8a461 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -5,6 +5,8 @@ */ namespace Magento\Framework\App; +use \Magento\Framework\App\FeedInterface; + class Feed implements \Magento\Framework\App\FeedInterface { /** @@ -26,9 +28,9 @@ public function __construct(\Zend_Feed_Abstract $feed) * @return string */ public function getFormatedContentAs( - $format = FeedOutputFormatsInterface::DEFAULT_FORMAT + $format = FeedInterface::DEFAULT_FORMAT ) { - if ($format === FeedOutputFormatsInterface::DEFAULT_FORMAT) { + if ($format === FeedInterface::DEFAULT_FORMAT) { return $this->feed->saveXml(); } throw new \Magento\Framework\Exception\RuntimeException( diff --git a/lib/internal/Magento/Framework/App/FeedFactory.php b/lib/internal/Magento/Framework/App/FeedFactory.php index f198b4ad90f0f..6ee3775b61687 100644 --- a/lib/internal/Magento/Framework/App/FeedFactory.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -6,12 +6,13 @@ namespace Magento\Framework\App; use Magento\Framework\App\FeedFactory; +use Magento\Framework\App\FeedFactoryInterface; use Psr\Log\LoggerInterface; /** * Feed factory */ -class FeedFactory implements \Magento\Framework\App\FeedFactoryInterface +class FeedFactory implements FeedFactoryInterface { /** * @var \Zend_Feed @@ -38,18 +39,20 @@ public function __construct( /** * Get a new \Magento\Framework\App\Feed object from a custom array * - * @throws \Magento\Framework\Exception\RuntimeException + * @throws \Magento\Framework\Exception\InputException * @param array $data * @param string $format * @return \Magento\Framework\App\FeedInterface */ - public function importArray(array $data, $format = FeedFormatsInterface::DEFAULT_FORMAT) - { + public function create( + array $data, + $format = FeedFactoryInterface::DEFAULT_FORMAT + ) { try { return $this->feedProcessor->importArray($data, $format); } catch (\Zend_Feed_Exception $e) { $this->logger->error($e->getMessage()); - throw new \Magento\Framework\Exception\RuntimeException( + throw new \Magento\Framework\Exception\InputException( __('There has been an error with import'), $e ); diff --git a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php index 5147fccd638a7..2bc9dd735bdcb 100644 --- a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php +++ b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php @@ -8,6 +8,8 @@ interface FeedFactoryInterface { + const DEFAULT_FORMAT = 'rss'; + /** * Returns FeedInterface object from a custom array * @@ -16,8 +18,8 @@ interface FeedFactoryInterface * @param string $format * @return FeedInterface */ - public function importArray( + public function create( array $data, - $format = FeedFormatsInterface::DEFAULT_FORMAT + $format = self::DEFAULT_FORMAT ); } diff --git a/lib/internal/Magento/Framework/App/FeedFormatsInterface.php b/lib/internal/Magento/Framework/App/FeedFormatsInterface.php deleted file mode 100644 index 027a89f7a47d2..0000000000000 --- a/lib/internal/Magento/Framework/App/FeedFormatsInterface.php +++ /dev/null @@ -1,11 +0,0 @@ - Date: Wed, 13 Sep 2017 17:17:39 +0300 Subject: [PATCH 0013/2023] magento/magento2#9347: Zend feed refactoring - Coding style fixes per Travis CI static tests results --- app/code/Magento/Rss/Model/Rss.php | 2 +- lib/internal/Magento/Framework/App/FeedFactory.php | 8 +++----- .../Magento/Framework/App/FeedFactoryInterface.php | 9 ++++----- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index e527319e53990..cff3daa83c209 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -102,7 +102,7 @@ public function setDataProvider(DataProviderInterface $dataProvider) public function createRssXml() { $feed = $this->feedFactory->importArray( - $this->getFeeds(), + $this->getFeeds(), \Magento\Framework\App\FeedFormatsInterface::DEFAULT_FORMAT ); diff --git a/lib/internal/Magento/Framework/App/FeedFactory.php b/lib/internal/Magento/Framework/App/FeedFactory.php index 6ee3775b61687..c260b4d057fce 100644 --- a/lib/internal/Magento/Framework/App/FeedFactory.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -5,8 +5,6 @@ */ namespace Magento\Framework\App; -use Magento\Framework\App\FeedFactory; -use Magento\Framework\App\FeedFactoryInterface; use Psr\Log\LoggerInterface; /** @@ -40,12 +38,12 @@ public function __construct( * Get a new \Magento\Framework\App\Feed object from a custom array * * @throws \Magento\Framework\Exception\InputException - * @param array $data - * @param string $format + * @param array $data + * @param string $format * @return \Magento\Framework\App\FeedInterface */ public function create( - array $data, + array $data, $format = FeedFactoryInterface::DEFAULT_FORMAT ) { try { diff --git a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php index 2bc9dd735bdcb..f7f1066b5d50f 100644 --- a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php +++ b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php @@ -7,19 +7,18 @@ interface FeedFactoryInterface { - const DEFAULT_FORMAT = 'rss'; /** * Returns FeedInterface object from a custom array - * + * * @throws \Magento\Framework\Exception\RuntimeException - * @param array $data - * @param string $format + * @param array $data + * @param string $format * @return FeedInterface */ public function create( - array $data, + array $data, $format = self::DEFAULT_FORMAT ); } From 0b51e8c67c9285df1de8c70e23ae109cc8da98f9 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Wed, 13 Sep 2017 17:26:28 +0300 Subject: [PATCH 0014/2023] magento/magento2#9347: Zend feed refactoring - Minor fixes per Travis CI unit tests results --- app/code/Magento/Rss/Model/Rss.php | 6 +++--- app/code/Magento/Rss/Test/Unit/Model/RssTest.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index cff3daa83c209..6d9754f12f0f6 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -101,13 +101,13 @@ public function setDataProvider(DataProviderInterface $dataProvider) */ public function createRssXml() { - $feed = $this->feedFactory->importArray( + $feed = $this->feedFactory->create( $this->getFeeds(), - \Magento\Framework\App\FeedFormatsInterface::DEFAULT_FORMAT + \Magento\Framework\App\FeedFactoryInterface::DEFAULT_FORMAT ); return $feed->getFormatedContentAs( - \Magento\Framework\App\FeedOutputFormatsInterface::DEFAULT_FORMAT + \Magento\Framework\App\FeedInterface::DEFAULT_FORMAT ); } } diff --git a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php index 5f8f8007314a4..935ef425c11e3 100644 --- a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php +++ b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php @@ -153,12 +153,12 @@ public function testCreateRssXml() $this->feedMock->expects($this->once()) ->method('getFormatedContentAs') - ->with(\Magento\Framework\App\FeedOutputFormatsInterface::DEFAULT_FORMAT) + ->with(\Magento\Framework\App\FeedInterface::DEFAULT_FORMAT) ->will($this->returnValue($this->feedXml)); $this->feedFactoryMock->expects($this->once()) - ->method('importArray') - ->with($this->feedData, \Magento\Framework\App\FeedFormatsInterface::DEFAULT_FORMAT) + ->method('create') + ->with($this->feedData, \Magento\Framework\App\FeedFactoryInterface::DEFAULT_FORMAT) ->will($this->returnValue($this->feedMock)); $this->rss->setDataProvider($dataProvider); From 74d431a08e53c0fc7e35bc185434c93a801d68b0 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Wed, 13 Sep 2017 17:41:47 +0300 Subject: [PATCH 0015/2023] magento/magento2#9347: Zend feed refactoring - Minor fixes per CR --- app/code/Magento/Rss/Model/Rss.php | 11 +++-------- app/code/Magento/Rss/Test/Unit/Model/RssTest.php | 2 +- lib/internal/Magento/Framework/App/Feed.php | 15 ++++++++------- .../Magento/Framework/App/FeedInterface.php | 5 ++--- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index 6d9754f12f0f6..138cd5f004f83 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -9,6 +9,7 @@ use Magento\Framework\App\Rss\DataProviderInterface; use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\App\FeedFactoryInterface; +use Magento\Framework\App\FeedInterface; /** * Provides functionality to work with RSS feeds @@ -101,13 +102,7 @@ public function setDataProvider(DataProviderInterface $dataProvider) */ public function createRssXml() { - $feed = $this->feedFactory->create( - $this->getFeeds(), - \Magento\Framework\App\FeedFactoryInterface::DEFAULT_FORMAT - ); - - return $feed->getFormatedContentAs( - \Magento\Framework\App\FeedInterface::DEFAULT_FORMAT - ); + $feed = $this->feedFactory->create($this->getFeeds(), FeedFactoryInterface::DEFAULT_FORMAT); + return $feed->getFormattedContentAs(FeedInterface::DEFAULT_FORMAT); } } diff --git a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php index 935ef425c11e3..2102d463ed656 100644 --- a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php +++ b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php @@ -152,7 +152,7 @@ public function testCreateRssXml() $dataProvider->expects($this->any())->method('getRssData')->will($this->returnValue($this->feedData)); $this->feedMock->expects($this->once()) - ->method('getFormatedContentAs') + ->method('getFormattedContentAs') ->with(\Magento\Framework\App\FeedInterface::DEFAULT_FORMAT) ->will($this->returnValue($this->feedXml)); diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 8df5b63a8a461..173de90473574 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -5,7 +5,8 @@ */ namespace Magento\Framework\App; -use \Magento\Framework\App\FeedInterface; +use Magento\Framework\Phrase; +use Magento\Framework\Exception\InputException; class Feed implements \Magento\Framework\App\FeedInterface { @@ -25,17 +26,17 @@ public function __construct(\Zend_Feed_Abstract $feed) /** * Get the xml from Zend_Feed_Abstract object * + * @param string $format * @return string + * @throws InputException */ - public function getFormatedContentAs( - $format = FeedInterface::DEFAULT_FORMAT - ) { + public function getFormattedContentAs(string $format = FeedInterface::DEFAULT_FORMAT): string + { if ($format === FeedInterface::DEFAULT_FORMAT) { return $this->feed->saveXml(); } - throw new \Magento\Framework\Exception\RuntimeException( - __('Given feed format is not supported'), - $e + throw new InputException( + new Phrase('Given feed format is not supported') ); } } diff --git a/lib/internal/Magento/Framework/App/FeedInterface.php b/lib/internal/Magento/Framework/App/FeedInterface.php index bfd432d01ad81..4ab132c38bb92 100644 --- a/lib/internal/Magento/Framework/App/FeedInterface.php +++ b/lib/internal/Magento/Framework/App/FeedInterface.php @@ -10,9 +10,8 @@ interface FeedInterface const DEFAULT_FORMAT = 'xml'; /** + * @param string $format * @return string */ - public function getFormatedContentAs( - $format = self::DEFAULT_FORMAT - ); + public function getFormattedContentAs(string $format = self::DEFAULT_FORMAT): string; } From 7f73d67058718202210f95c76655dfa35f00351d Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Mon, 25 Sep 2017 13:56:21 +0200 Subject: [PATCH 0016/2023] Zend Feed refactoring WIP --- app/code/Magento/Rss/Model/Rss.php | 9 ++-- app/etc/di.xml | 12 ++++++ lib/internal/Magento/Framework/App/Feed.php | 42 +++++++++---------- .../Magento/Framework/App/FeedFactory.php | 35 ++++++++++++---- .../Framework/App/FeedFactoryInterface.php | 2 +- .../Magento/Framework/App/FeedInterface.php | 2 +- 6 files changed, 65 insertions(+), 37 deletions(-) diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index e527319e53990..051417140be89 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -8,6 +8,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Rss\DataProviderInterface; use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\App\FeedInterface; use Magento\Framework\App\FeedFactoryInterface; /** @@ -101,13 +102,13 @@ public function setDataProvider(DataProviderInterface $dataProvider) */ public function createRssXml() { - $feed = $this->feedFactory->importArray( + $feed = $this->feedFactory->create( $this->getFeeds(), - \Magento\Framework\App\FeedFormatsInterface::DEFAULT_FORMAT + FeedFactoryInterface::DEFAULT_FORMAT ); - return $feed->getFormatedContentAs( - \Magento\Framework\App\FeedOutputFormatsInterface::DEFAULT_FORMAT + return $feed->getFormattedContentAs( + FeedInterface::DEFAULT_FORMAT ); } } diff --git a/app/etc/di.xml b/app/etc/di.xml index 0bf625b402469..ba3da12e7b435 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -174,6 +174,11 @@ + + + Magento\Framework\Acl\Builder\Proxy + + @@ -243,6 +248,13 @@ + + + + Magento\Framework\App\Feed + + + Cm\RedisSession\Handler\ConfigInterface diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 8df5b63a8a461..9a4f3235a42f4 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -5,37 +5,35 @@ */ namespace Magento\Framework\App; -use \Magento\Framework\App\FeedInterface; - -class Feed implements \Magento\Framework\App\FeedInterface +/** + * Default XML feed class + */ +class Feed implements FeedInterface { /** - * @var \Zend_Feed_Abstract + * @param Zend_Feed $feed + * @param array $data */ - private $feed; - - /** - * @param \Zend_Feed_Abstract $feed - */ - public function __construct(\Zend_Feed_Abstract $feed) - { - $this->feed = $feed; + public function __construct( + \Zend_Feed $feed, + array $data + ) { + $this->feed = $feed; + $this->data = $data; } /** - * Get the xml from Zend_Feed_Abstract object - * + * Returns the formatted feed content + * * @return string */ public function getFormatedContentAs( - $format = FeedInterface::DEFAULT_FORMAT + $format = self::DEFAULT_FORMAT ) { - if ($format === FeedInterface::DEFAULT_FORMAT) { - return $this->feed->saveXml(); - } - throw new \Magento\Framework\Exception\RuntimeException( - __('Given feed format is not supported'), - $e + $feed = $this->feed::importArray( + $this->data, + FeedFactoryInterface::DEFAULT_FORMAT ); + return $this->feed->saveXml(); } -} +} \ No newline at end of file diff --git a/lib/internal/Magento/Framework/App/FeedFactory.php b/lib/internal/Magento/Framework/App/FeedFactory.php index 6ee3775b61687..08296ba84cf61 100644 --- a/lib/internal/Magento/Framework/App/FeedFactory.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -5,8 +5,8 @@ */ namespace Magento\Framework\App; -use Magento\Framework\App\FeedFactory; use Magento\Framework\App\FeedFactoryInterface; +use Magento\Framework\ObjectManagerInterface; use Psr\Log\LoggerInterface; /** @@ -15,7 +15,7 @@ class FeedFactory implements FeedFactoryInterface { /** - * @var \Zend_Feed + * @var FeedProcessorInterface */ private $feedProcessor; @@ -25,19 +25,27 @@ class FeedFactory implements FeedFactoryInterface private $logger; /** - * @param \Zend_Feed $feedProcessor + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * @param ObjectManagerInterface $objectManger * @param LoggerInterface $logger + * @param array $formats */ public function __construct( - \Zend_Feed $feedProcessor, - LoggerInterface $logger + ObjectManagerInterface $objectManger, + LoggerInterface $logger, + array $formats ) { - $this->feedProcessor = $feedProcessor; + $this->objectManager = $objectManger; $this->logger = $logger; + $this->formats = $formats; } /** - * Get a new \Magento\Framework\App\Feed object from a custom array + * Get a new \Magento\Framework\App\FeedInterface object from a custom array * * @throws \Magento\Framework\Exception\InputException * @param array $data @@ -48,9 +56,18 @@ public function create( array $data, $format = FeedFactoryInterface::DEFAULT_FORMAT ) { + if (!isset($this->formats[$format])) { + throw new \Magento\Framework\Exception\InputException( + __('The format is not supported'), + $e + ); + } try { - return $this->feedProcessor->importArray($data, $format); - } catch (\Zend_Feed_Exception $e) { + return $this->objectManager->create( + $this->formats[$format], + $data + ); + } catch (\Exception $e) { $this->logger->error($e->getMessage()); throw new \Magento\Framework\Exception\InputException( __('There has been an error with import'), diff --git a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php index 2bc9dd735bdcb..59608787fa01e 100644 --- a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php +++ b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php @@ -13,7 +13,7 @@ interface FeedFactoryInterface /** * Returns FeedInterface object from a custom array * - * @throws \Magento\Framework\Exception\RuntimeException + * @throws \Magento\Framework\Exception\InputException * @param array $data * @param string $format * @return FeedInterface diff --git a/lib/internal/Magento/Framework/App/FeedInterface.php b/lib/internal/Magento/Framework/App/FeedInterface.php index bfd432d01ad81..a856fba21e1a8 100644 --- a/lib/internal/Magento/Framework/App/FeedInterface.php +++ b/lib/internal/Magento/Framework/App/FeedInterface.php @@ -12,7 +12,7 @@ interface FeedInterface /** * @return string */ - public function getFormatedContentAs( + public function getFormattedContentAs( $format = self::DEFAULT_FORMAT ); } From 64610d359a54c57d04e73d391a020a297aeeac4f Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Mon, 25 Sep 2017 14:03:53 +0200 Subject: [PATCH 0017/2023] Removed the wrong lines commited --- app/etc/di.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/etc/di.xml b/app/etc/di.xml index ba3da12e7b435..03cf3294991ae 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -174,11 +174,6 @@ - - - Magento\Framework\Acl\Builder\Proxy - - From 32e2e4de5921ecb7b13722955298e886ec2b2d59 Mon Sep 17 00:00:00 2001 From: Lorenzo Stramaccia Date: Wed, 11 Oct 2017 12:34:46 +0200 Subject: [PATCH 0018/2023] Fix meta title property --- lib/internal/Magento/Framework/View/Page/Config.php | 1 + .../Magento/Framework/View/Page/Config/Renderer.php | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/lib/internal/Magento/Framework/View/Page/Config.php b/lib/internal/Magento/Framework/View/Page/Config.php index a5bbefb33008e..f12e2b56a60ac 100644 --- a/lib/internal/Magento/Framework/View/Page/Config.php +++ b/lib/internal/Magento/Framework/View/Page/Config.php @@ -117,6 +117,7 @@ class Config 'description' => null, 'keywords' => null, 'robots' => null, + 'title' => null, ]; /** diff --git a/lib/internal/Magento/Framework/View/Page/Config/Renderer.php b/lib/internal/Magento/Framework/View/Page/Config/Renderer.php index 9563cbfbcc532..a26e341f16dd7 100644 --- a/lib/internal/Magento/Framework/View/Page/Config/Renderer.php +++ b/lib/internal/Magento/Framework/View/Page/Config/Renderer.php @@ -136,6 +136,12 @@ public function renderMetadata() protected function processMetadataContent($name, $content) { $method = 'get' . $this->string->upperCaseWords($name, '_', ''); + if($name === 'title') { + if (!$content) { + $content = $this->escaper->escapeHtml($this->pageConfig->$method()->get()); + } + return $content; + } if (method_exists($this->pageConfig, $method)) { $content = $this->pageConfig->$method(); } From b11c7e78b24450ec4d3e73534c40ab427e786cdd Mon Sep 17 00:00:00 2001 From: Lorenzo Stramaccia Date: Thu, 12 Oct 2017 10:17:25 +0200 Subject: [PATCH 0019/2023] Update unit test --- .../Magento/Framework/View/Test/Unit/Page/ConfigTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Page/ConfigTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Page/ConfigTest.php index 400e9cf3d1ed7..23d391c7f4f8d 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Page/ConfigTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Page/ConfigTest.php @@ -13,7 +13,7 @@ use Magento\Framework\View\Page\Config; /** - * @covers Magento\Framework\View\Page\Config + * @covers \Magento\Framework\View\Page\Config * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -139,6 +139,7 @@ public function testMetadata() 'description' => null, 'keywords' => null, 'robots' => null, + 'title' => null, 'name' => 'test_value', 'html_encoded' => '<title><span class="test">Test</span></title>', ]; From 474e43cfb97617355d6d17ec7eb7639789319a7d Mon Sep 17 00:00:00 2001 From: Lorenzo Stramaccia Date: Thu, 12 Oct 2017 10:33:09 +0200 Subject: [PATCH 0020/2023] Fix coding standards --- lib/internal/Magento/Framework/View/Page/Config/Renderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Page/Config/Renderer.php b/lib/internal/Magento/Framework/View/Page/Config/Renderer.php index a26e341f16dd7..93c8c5c338627 100644 --- a/lib/internal/Magento/Framework/View/Page/Config/Renderer.php +++ b/lib/internal/Magento/Framework/View/Page/Config/Renderer.php @@ -136,7 +136,7 @@ public function renderMetadata() protected function processMetadataContent($name, $content) { $method = 'get' . $this->string->upperCaseWords($name, '_', ''); - if($name === 'title') { + if ($name === 'title') { if (!$content) { $content = $this->escaper->escapeHtml($this->pageConfig->$method()->get()); } From d2d397a7acfe29db9bc2d55213eea2f01f393567 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Thu, 16 Nov 2017 14:18:55 +0100 Subject: [PATCH 0021/2023] Fixing stuff as requested --- lib/internal/Magento/Framework/App/Feed.php | 6 +++--- lib/internal/Magento/Framework/App/FeedFactory.php | 14 +++++++++++--- .../Magento/Framework/App/FeedFactoryInterface.php | 4 ++-- .../Magento/Framework/App/FeedInterface.php | 4 ++-- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 9a4f3235a42f4..c9762c31157d7 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -27,12 +27,12 @@ public function __construct( * * @return string */ - public function getFormatedContentAs( - $format = self::DEFAULT_FORMAT + public function getFormattedContentAs( + $format = self::FORMAT_XML ) { $feed = $this->feed::importArray( $this->data, - FeedFactoryInterface::DEFAULT_FORMAT + FeedFactoryInterface::FORMAT_RSS ); return $this->feed->saveXml(); } diff --git a/lib/internal/Magento/Framework/App/FeedFactory.php b/lib/internal/Magento/Framework/App/FeedFactory.php index 08296ba84cf61..b4f3b56d9a8e0 100644 --- a/lib/internal/Magento/Framework/App/FeedFactory.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -27,7 +27,7 @@ class FeedFactory implements FeedFactoryInterface /** * @var ObjectManagerInterface */ - protected $objectManager; + private $objectManager; /** * @param ObjectManagerInterface $objectManger @@ -54,7 +54,7 @@ public function __construct( */ public function create( array $data, - $format = FeedFactoryInterface::DEFAULT_FORMAT + $format = FeedFactoryInterface::FORMAT_RSS ) { if (!isset($this->formats[$format])) { throw new \Magento\Framework\Exception\InputException( @@ -62,6 +62,14 @@ public function create( $e ); } + + if (!is_subclass_of($this->formats[$format], '\Magento\Framework\App\FeedInterface')) { + throw new \Magento\Framework\Exception\InputException( + __('Wrong format handler type'), + $e + ); + } + try { return $this->objectManager->create( $this->formats[$format], @@ -69,7 +77,7 @@ public function create( ); } catch (\Exception $e) { $this->logger->error($e->getMessage()); - throw new \Magento\Framework\Exception\InputException( + throw new \Magento\Framework\Exception\RuntimeException( __('There has been an error with import'), $e ); diff --git a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php index 59608787fa01e..0d51040b4088c 100644 --- a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php +++ b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php @@ -8,7 +8,7 @@ interface FeedFactoryInterface { - const DEFAULT_FORMAT = 'rss'; + const FORMAT_RSS = 'rss'; /** * Returns FeedInterface object from a custom array @@ -20,6 +20,6 @@ interface FeedFactoryInterface */ public function create( array $data, - $format = self::DEFAULT_FORMAT + $format = self::FORMAT_RSS ); } diff --git a/lib/internal/Magento/Framework/App/FeedInterface.php b/lib/internal/Magento/Framework/App/FeedInterface.php index a856fba21e1a8..29a055841ff0e 100644 --- a/lib/internal/Magento/Framework/App/FeedInterface.php +++ b/lib/internal/Magento/Framework/App/FeedInterface.php @@ -7,12 +7,12 @@ interface FeedInterface { - const DEFAULT_FORMAT = 'xml'; + const FORMAT_XML = 'xml'; /** * @return string */ public function getFormattedContentAs( - $format = self::DEFAULT_FORMAT + $format = self::FORMAT_XML ); } From 07702273cc86b6aebea9fc37eb37cb09932968a7 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Thu, 23 Nov 2017 17:32:16 +0100 Subject: [PATCH 0022/2023] Some code style fixes --- lib/internal/Magento/Framework/App/Feed.php | 2 ++ lib/internal/Magento/Framework/App/FeedFactory.php | 9 ++------- .../Magento/Framework/App/FeedFactoryInterface.php | 8 +++++++- lib/internal/Magento/Framework/App/FeedInterface.php | 8 ++++++++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index c9762c31157d7..1e7dc89e932e3 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -24,6 +24,8 @@ public function __construct( /** * Returns the formatted feed content + * + * @param string $format * * @return string */ diff --git a/lib/internal/Magento/Framework/App/FeedFactory.php b/lib/internal/Magento/Framework/App/FeedFactory.php index b4f3b56d9a8e0..50d03ffd65cd3 100644 --- a/lib/internal/Magento/Framework/App/FeedFactory.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -45,12 +45,7 @@ public function __construct( } /** - * Get a new \Magento\Framework\App\FeedInterface object from a custom array - * - * @throws \Magento\Framework\Exception\InputException - * @param array $data - * @param string $format - * @return \Magento\Framework\App\FeedInterface + * {@inheritdoc} */ public function create( array $data, @@ -63,7 +58,7 @@ public function create( ); } - if (!is_subclass_of($this->formats[$format], '\Magento\Framework\App\FeedInterface')) { + if (!is_subclass_of($this->formats[$format], \Magento\Framework\App\FeedInterface::class)) { throw new \Magento\Framework\Exception\InputException( __('Wrong format handler type'), $e diff --git a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php index 0d51040b4088c..5b534c547afe3 100644 --- a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php +++ b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php @@ -5,15 +5,21 @@ */ namespace Magento\Framework\App; +/** + * Feed factory interface + */ interface FeedFactoryInterface { - + /** + * RSS feed input format + */ const FORMAT_RSS = 'rss'; /** * Returns FeedInterface object from a custom array * * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\RuntimeException * @param array $data * @param string $format * @return FeedInterface diff --git a/lib/internal/Magento/Framework/App/FeedInterface.php b/lib/internal/Magento/Framework/App/FeedInterface.php index 29a055841ff0e..24858767db7c4 100644 --- a/lib/internal/Magento/Framework/App/FeedInterface.php +++ b/lib/internal/Magento/Framework/App/FeedInterface.php @@ -5,11 +5,19 @@ */ namespace Magento\Framework\App; +/** + * Feed interface + */ interface FeedInterface { + /** + * XML feed output format + */ const FORMAT_XML = 'xml'; /** + * @param string $format + * * @return string */ public function getFormattedContentAs( From 735c840c731bf9b26e2da5723c3802fb158e54c8 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Thu, 23 Nov 2017 17:33:46 +0100 Subject: [PATCH 0023/2023] RSS model fix --- app/code/Magento/Rss/Model/Rss.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index 051417140be89..2f0d044eecd4e 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -104,11 +104,11 @@ public function createRssXml() { $feed = $this->feedFactory->create( $this->getFeeds(), - FeedFactoryInterface::DEFAULT_FORMAT + FeedFactoryInterface::FORMAT_RSS ); return $feed->getFormattedContentAs( - FeedInterface::DEFAULT_FORMAT + FeedInterface::FORMAT_RSS ); } } From 7e17d2077a75df92afb39815bc91b0dd42a70b85 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Fri, 24 Nov 2017 12:33:30 +0100 Subject: [PATCH 0024/2023] Unit test fix --- app/code/Magento/Rss/Test/Unit/Model/RssTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php index 2102d463ed656..8a5d2efd756a8 100644 --- a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php +++ b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php @@ -153,12 +153,12 @@ public function testCreateRssXml() $this->feedMock->expects($this->once()) ->method('getFormattedContentAs') - ->with(\Magento\Framework\App\FeedInterface::DEFAULT_FORMAT) + ->with(\Magento\Framework\App\FeedInterface::FORMAT_XML) ->will($this->returnValue($this->feedXml)); $this->feedFactoryMock->expects($this->once()) ->method('create') - ->with($this->feedData, \Magento\Framework\App\FeedFactoryInterface::DEFAULT_FORMAT) + ->with($this->feedData, \Magento\Framework\App\FeedFactoryInterface::FORMAT_RSS) ->will($this->returnValue($this->feedMock)); $this->rss->setDataProvider($dataProvider); From 46c51baf04020995a98c0c6f70e64eca6b14e1fe Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Fri, 24 Nov 2017 12:34:09 +0100 Subject: [PATCH 0025/2023] RSS model fix --- app/code/Magento/Rss/Model/Rss.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index 2f0d044eecd4e..eb83ddd0ee4dc 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -108,7 +108,7 @@ public function createRssXml() ); return $feed->getFormattedContentAs( - FeedInterface::FORMAT_RSS + FeedInterface::FORMAT_XML ); } } From 3a3683f0a7244078609cd0e512ce6743af8c322b Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Fri, 22 Dec 2017 16:49:16 +0100 Subject: [PATCH 0026/2023] Code style fixes --- app/code/Magento/Rss/Model/Rss.php | 2 +- lib/internal/Magento/Framework/App/Feed.php | 10 +++++----- lib/internal/Magento/Framework/App/FeedFactory.php | 4 ++-- .../Magento/Framework/App/FeedFactoryInterface.php | 4 ++-- lib/internal/Magento/Framework/App/FeedInterface.php | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index eb83ddd0ee4dc..200ffb967ad1a 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -103,7 +103,7 @@ public function setDataProvider(DataProviderInterface $dataProvider) public function createRssXml() { $feed = $this->feedFactory->create( - $this->getFeeds(), + $this->getFeeds(), FeedFactoryInterface::FORMAT_RSS ); diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 1e7dc89e932e3..63d56260bf34a 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -18,24 +18,24 @@ public function __construct( \Zend_Feed $feed, array $data ) { - $this->feed = $feed; - $this->data = $data; + $this->feed = $feed; + $this->data = $data; } /** * Returns the formatted feed content * * @param string $format - * + * * @return string */ public function getFormattedContentAs( $format = self::FORMAT_XML ) { $feed = $this->feed::importArray( - $this->data, + $this->data, FeedFactoryInterface::FORMAT_RSS ); return $this->feed->saveXml(); } -} \ No newline at end of file +} diff --git a/lib/internal/Magento/Framework/App/FeedFactory.php b/lib/internal/Magento/Framework/App/FeedFactory.php index 50d03ffd65cd3..57eaca03245fc 100644 --- a/lib/internal/Magento/Framework/App/FeedFactory.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -48,7 +48,7 @@ public function __construct( * {@inheritdoc} */ public function create( - array $data, + array $data, $format = FeedFactoryInterface::FORMAT_RSS ) { if (!isset($this->formats[$format])) { @@ -62,7 +62,7 @@ public function create( throw new \Magento\Framework\Exception\InputException( __('Wrong format handler type'), $e - ); + ); } try { diff --git a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php index 5b534c547afe3..b35e3379f9f19 100644 --- a/lib/internal/Magento/Framework/App/FeedFactoryInterface.php +++ b/lib/internal/Magento/Framework/App/FeedFactoryInterface.php @@ -17,7 +17,7 @@ interface FeedFactoryInterface /** * Returns FeedInterface object from a custom array - * + * * @throws \Magento\Framework\Exception\InputException * @throws \Magento\Framework\Exception\RuntimeException * @param array $data @@ -25,7 +25,7 @@ interface FeedFactoryInterface * @return FeedInterface */ public function create( - array $data, + array $data, $format = self::FORMAT_RSS ); } diff --git a/lib/internal/Magento/Framework/App/FeedInterface.php b/lib/internal/Magento/Framework/App/FeedInterface.php index 24858767db7c4..661f8a65e70ac 100644 --- a/lib/internal/Magento/Framework/App/FeedInterface.php +++ b/lib/internal/Magento/Framework/App/FeedInterface.php @@ -10,14 +10,14 @@ */ interface FeedInterface { - /** + /** * XML feed output format */ const FORMAT_XML = 'xml'; /** * @param string $format - * + * * @return string */ public function getFormattedContentAs( From 6311d5cf7444436245e4326051a893f290e70bcd Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Fri, 22 Dec 2017 17:50:27 +0100 Subject: [PATCH 0027/2023] Code fixes --- lib/internal/Magento/Framework/App/Feed.php | 2 +- lib/internal/Magento/Framework/App/FeedFactory.php | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 63d56260bf34a..01634be6bfaf4 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -36,6 +36,6 @@ public function getFormattedContentAs( $this->data, FeedFactoryInterface::FORMAT_RSS ); - return $this->feed->saveXml(); + return $feed->saveXml(); } } diff --git a/lib/internal/Magento/Framework/App/FeedFactory.php b/lib/internal/Magento/Framework/App/FeedFactory.php index 57eaca03245fc..129341824f58d 100644 --- a/lib/internal/Magento/Framework/App/FeedFactory.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -14,11 +14,6 @@ */ class FeedFactory implements FeedFactoryInterface { - /** - * @var FeedProcessorInterface - */ - private $feedProcessor; - /** * @var LoggerInterface */ @@ -53,14 +48,14 @@ public function create( ) { if (!isset($this->formats[$format])) { throw new \Magento\Framework\Exception\InputException( - __('The format is not supported'), + new \Magento\Framework\Phrase('The format is not supported'), $e ); } if (!is_subclass_of($this->formats[$format], \Magento\Framework\App\FeedInterface::class)) { throw new \Magento\Framework\Exception\InputException( - __('Wrong format handler type'), + new \Magento\Framework\Phrase('Wrong format handler type'), $e ); } @@ -73,7 +68,7 @@ public function create( } catch (\Exception $e) { $this->logger->error($e->getMessage()); throw new \Magento\Framework\Exception\RuntimeException( - __('There has been an error with import'), + new \Magento\Framework\Phrase('There has been an error with import'), $e ); } From 4462eaf918f1e8d7362c19cba6bb6db2175efc64 Mon Sep 17 00:00:00 2001 From: Dusan Lukic Date: Fri, 22 Dec 2017 17:57:08 +0100 Subject: [PATCH 0028/2023] Added some missing properties and renamed stuff --- lib/internal/Magento/Framework/App/Feed.php | 18 ++++++++++++++---- .../Magento/Framework/App/FeedFactory.php | 9 +++++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Feed.php b/lib/internal/Magento/Framework/App/Feed.php index 01634be6bfaf4..a76acc2486eb0 100644 --- a/lib/internal/Magento/Framework/App/Feed.php +++ b/lib/internal/Magento/Framework/App/Feed.php @@ -11,14 +11,24 @@ class Feed implements FeedInterface { /** - * @param Zend_Feed $feed + * @var \Zend_Feed + */ + private $feedProcessor; + + /** + * @var array + */ + private $data; + + /** + * @param Zend_Feed $feedProcessor * @param array $data */ public function __construct( - \Zend_Feed $feed, + \Zend_Feed $feedProcessor, array $data ) { - $this->feed = $feed; + $this->feedProcessor = $feedProcessor; $this->data = $data; } @@ -32,7 +42,7 @@ public function __construct( public function getFormattedContentAs( $format = self::FORMAT_XML ) { - $feed = $this->feed::importArray( + $feed = $this->feedProcessor::importArray( $this->data, FeedFactoryInterface::FORMAT_RSS ); diff --git a/lib/internal/Magento/Framework/App/FeedFactory.php b/lib/internal/Magento/Framework/App/FeedFactory.php index 129341824f58d..87bd87fdc84c2 100644 --- a/lib/internal/Magento/Framework/App/FeedFactory.php +++ b/lib/internal/Magento/Framework/App/FeedFactory.php @@ -14,15 +14,20 @@ */ class FeedFactory implements FeedFactoryInterface { + /** + * @var ObjectManagerInterface + */ + private $objectManager; + /** * @var LoggerInterface */ private $logger; /** - * @var ObjectManagerInterface + * @var array */ - private $objectManager; + private $formats; /** * @param ObjectManagerInterface $objectManger From 07a4b3b595407fac5383b09d9bf0669f68dd94f4 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 1 Nov 2017 16:25:02 +0530 Subject: [PATCH 0029/2023] #8810 - REST API - Attribute option creation -> no ID returned --- .../Api/ProductAttributeOptionManagementInterface.php | 2 +- .../Eav/Api/AttributeOptionManagementInterface.php | 2 +- .../Eav/Model/Entity/Attribute/OptionManagement.php | 8 ++++++-- .../Unit/Model/Entity/Attribute/OptionManagementTest.php | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php b/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php index 07b7d591c3fd7..9e0014f242ba7 100644 --- a/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php +++ b/app/code/Magento/Catalog/Api/ProductAttributeOptionManagementInterface.php @@ -29,7 +29,7 @@ public function getItems($attributeCode); * @param \Magento\Eav\Api\Data\AttributeOptionInterface $option * @throws \Magento\Framework\Exception\StateException * @throws \Magento\Framework\Exception\InputException - * @return bool + * @return \Magento\Eav\Api\Data\AttributeOptionInterface */ public function add($attributeCode, $option); diff --git a/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php b/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php index aac6e2174b1ea..566149bbd2e14 100644 --- a/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php +++ b/app/code/Magento/Eav/Api/AttributeOptionManagementInterface.php @@ -20,7 +20,7 @@ interface AttributeOptionManagementInterface * @param \Magento\Eav\Api\Data\AttributeOptionInterface $option * @throws \Magento\Framework\Exception\StateException * @throws \Magento\Framework\Exception\InputException - * @return bool + * @return \Magento\Eav\Api\Data\AttributeOptionInterface */ public function add($entityType, $attributeCode, $option); diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php index b0508fd8cc626..11b72754a95a3 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php @@ -49,9 +49,10 @@ public function add($entityType, $attributeCode, $option) throw new StateException(__('Attribute %1 doesn\'t work with options', $attributeCode)); } + $optionLabel = $option->getLabel(); $optionId = $this->getOptionId($option); $options = []; - $options['value'][$optionId][0] = $option->getLabel(); + $options['value'][$optionId][0] = $optionLabel; $options['order'][$optionId] = $option->getSortOrder(); if (is_array($option->getStoreLabels())) { @@ -67,11 +68,14 @@ public function add($entityType, $attributeCode, $option) $attribute->setOption($options); try { $this->resourceModel->save($attribute); + if ($optionLabel && $attribute->getAttributeCode()) { + $option->setValue($attribute->getSource()->getOptionId($optionLabel)); + } } catch (\Exception $e) { throw new StateException(__('Cannot save attribute %1', $attributeCode)); } - return true; + return $option; } /** diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php index 36eb78fd435e7..ed15d372f3f6b 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php @@ -80,7 +80,7 @@ public function testAdd() $attributeMock->expects($this->once())->method('setDefault')->with(['new_option']); $attributeMock->expects($this->once())->method('setOption')->with($option); $this->resourceModelMock->expects($this->once())->method('save')->with($attributeMock); - $this->assertTrue($this->model->add($entityType, $attributeCode, $optionMock)); + $this->assertEquals($optionMock, $this->model->add($entityType, $attributeCode, $optionMock)); } /** From b9e0abe7d92458d075a2c5b472d07baadfcf9771 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 8 Jan 2018 21:47:56 +0530 Subject: [PATCH 0030/2023] #8810 - Solved api functional test issue --- .../Entity/Attribute/OptionManagement.php | 24 ++++++++++++++++++- ...AttributeOptionManagementInterfaceTest.php | 2 +- ...AttributeOptionManagementInterfaceTest.php | 2 +- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php index 11b72754a95a3..467de64b45c6d 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php @@ -69,7 +69,7 @@ public function add($entityType, $attributeCode, $option) try { $this->resourceModel->save($attribute); if ($optionLabel && $attribute->getAttributeCode()) { - $option->setValue($attribute->getSource()->getOptionId($optionLabel)); + $this->setOptionValue($option, $attribute, $optionLabel); } } catch (\Exception $e) { throw new StateException(__('Cannot save attribute %1', $attributeCode)); @@ -151,4 +151,26 @@ private function getOptionId($option) { return $option->getValue() ?: 'new_option'; } + + /** + * @param \Magento\Eav\Api\Data\AttributeOptionInterface $option + * @param \Magento\Eav\Api\Data\AttributeInterface $attribute + * @param string $optionLabel + * @return void + */ + public function setOptionValue($option, $attribute, $optionLabel) + { + if ($optionId = $attribute->getSource()->getOptionId($optionLabel)) { + $option->setValue($attribute->getSource()->getOptionId($optionId)); + } else { + if (is_array($option->getStoreLabels())) { + foreach ($option->getStoreLabels() as $label) { + if ($optionId = $attribute->getSource()->getOptionId($label->getLabel())) { + $option->setValue($attribute->getSource()->getOptionId($optionId)); + break; + } + } + } + } + } } diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php index 6c1e351ccd1ee..7de3f864b20a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeOptionManagementInterfaceTest.php @@ -74,7 +74,7 @@ public function testAdd($optionData) ] ); - $this->assertTrue($response); + $this->assertNotNull($response[AttributeOptionInterface::VALUE]); $updatedData = $this->getAttributeOptions($testAttributeCode); $lastOption = array_pop($updatedData); $this->assertEquals( diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php index 63e5282c22104..2a749b0b95177 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductSwatchAttributeOptionManagementInterfaceTest.php @@ -42,7 +42,7 @@ public function testAdd($optionData) ] ); - $this->assertTrue($response); + $this->assertNotNull($response[AttributeOptionInterface::VALUE]); $updatedData = $this->getAttributeOptions($testAttributeCode); $lastOption = array_pop($updatedData); $this->assertEquals( From e31ea928984ceed9f5a20c49c7bc3483d2bbe49d Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Tue, 9 Jan 2018 12:18:00 +0530 Subject: [PATCH 0031/2023] #8810 - fixed php code style issue --- .../Model/Entity/Attribute/OptionManagement.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php index 467de64b45c6d..46b1d3c7a539f 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php @@ -158,17 +158,16 @@ private function getOptionId($option) * @param string $optionLabel * @return void */ - public function setOptionValue($option, $attribute, $optionLabel) + protected function setOptionValue($option, $attribute, $optionLabel) { - if ($optionId = $attribute->getSource()->getOptionId($optionLabel)) { + $optionId = $attribute->getSource()->getOptionId($optionLabel); + if ($optionId) { $option->setValue($attribute->getSource()->getOptionId($optionId)); - } else { - if (is_array($option->getStoreLabels())) { - foreach ($option->getStoreLabels() as $label) { - if ($optionId = $attribute->getSource()->getOptionId($label->getLabel())) { - $option->setValue($attribute->getSource()->getOptionId($optionId)); - break; - } + } elseif (is_array($option->getStoreLabels())) { + foreach ($option->getStoreLabels() as $label) { + if ($optionId = $attribute->getSource()->getOptionId($label->getLabel())) { + $option->setValue($attribute->getSource()->getOptionId($optionId)); + break; } } } From cd2645053091d5cee7262149dff77ad82a895978 Mon Sep 17 00:00:00 2001 From: Sergey Date: Mon, 5 Feb 2018 16:20:47 +0300 Subject: [PATCH 0032/2023] [Improvement] Implement customer group grid on ui component --- .../ResourceModel/Group/Grid/Collection.php | 130 ++++++++++++++++- .../Group/Grid/CollectionTest.php | 128 +++++++++++++++++ .../Listing/Column/GroupActionsTest.php | 133 ++++++++++++++++++ .../Component/Listing/Column/GroupActions.php | 106 ++++++++++++++ app/code/Magento/Customer/etc/di.xml | 9 ++ .../adminhtml/layout/customer_group_index.xml | 43 +----- .../ui_component/customer_group_listing.xml | 76 ++++++++++ 7 files changed, 582 insertions(+), 43 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Group/Grid/CollectionTest.php create mode 100644 app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/GroupActionsTest.php create mode 100644 app/code/Magento/Customer/Ui/Component/Listing/Column/GroupActions.php create mode 100644 app/code/Magento/Customer/view/adminhtml/ui_component/customer_group_listing.xml diff --git a/app/code/Magento/Customer/Model/ResourceModel/Group/Grid/Collection.php b/app/code/Magento/Customer/Model/ResourceModel/Group/Grid/Collection.php index bf3400c3a2f68..f264245b30c4a 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/Group/Grid/Collection.php +++ b/app/code/Magento/Customer/Model/ResourceModel/Group/Grid/Collection.php @@ -7,8 +7,62 @@ */ namespace Magento\Customer\Model\ResourceModel\Group\Grid; -class Collection extends \Magento\Customer\Model\ResourceModel\Group\Collection +use Magento\Customer\Model\ResourceModel\Group\Collection as GroupCollection; +use Magento\Framework\Api\Search\SearchResultInterface; +use Magento\Framework\Search\AggregationInterface; + +/** + * Collection for displaying grid of customer groups + */ +class Collection extends GroupCollection implements SearchResultInterface { + /** + * @var AggregationInterface + */ + protected $aggregations; + + /** + * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory + * @param \Psr\Log\LoggerInterface $logger + * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy + * @param \Magento\Framework\Event\ManagerInterface $eventManager + * @param string $mainTable + * @param string $eventPrefix + * @param string $eventObject + * @param string $resourceModel + * @param string $model + * @param \Magento\Framework\DB\Adapter\AdapterInterface|string|null $connection + * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory, + \Psr\Log\LoggerInterface $logger, + \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, + \Magento\Framework\Event\ManagerInterface $eventManager, + $mainTable, + $eventPrefix, + $eventObject, + $resourceModel, + $model = \Magento\Framework\View\Element\UiComponent\DataProvider\Document::class, + $connection = null, + \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null + ) { + parent::__construct( + $entityFactory, + $logger, + $fetchStrategy, + $eventManager, + $connection, + $resource + ); + $this->_eventPrefix = $eventPrefix; + $this->_eventObject = $eventObject; + $this->_init($model, $resourceModel); + $this->setMainTable($mainTable); + } + /** * Resource initialization * @return $this @@ -19,4 +73,78 @@ protected function _initSelect() $this->addTaxClass(); return $this; } + + /** + * @return AggregationInterface + */ + public function getAggregations() + { + return $this->aggregations; + } + + /** + * @param AggregationInterface $aggregations + * @return $this + */ + public function setAggregations($aggregations) + { + $this->aggregations = $aggregations; + return $this; + } + + /** + * Get search criteria. + * + * @return \Magento\Framework\Api\SearchCriteriaInterface|null + */ + public function getSearchCriteria() + { + return null; + } + + /** + * Set search criteria. + * + * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria + * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function setSearchCriteria(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria = null) + { + return $this; + } + + /** + * Get total count. + * + * @return int + */ + public function getTotalCount() + { + return $this->getSize(); + } + + /** + * Set total count. + * + * @param int $totalCount + * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function setTotalCount($totalCount) + { + return $this; + } + + /** + * Set items list. + * + * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items + * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function setItems(array $items = null) + { + return $this; + } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Group/Grid/CollectionTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Group/Grid/CollectionTest.php new file mode 100644 index 0000000000000..d54c3188e5728 --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/Group/Grid/CollectionTest.php @@ -0,0 +1,128 @@ +entityFactoryMock = $this->getMockBuilder(EntityFactoryInterface::class) + ->getMockForAbstractClass(); + $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) + ->getMockForAbstractClass(); + $this->fetchStrategyMock = $this->getMockBuilder(FetchStrategyInterface::class) + ->getMockForAbstractClass(); + $this->eventManagerMock = $this->getMockBuilder(ManagerInterface::class) + ->getMockForAbstractClass(); + $this->resourceMock = $this->getMockBuilder(AbstractDb::class) + ->disableOriginalConstructor() + ->getMock(); + $this->aggregationsMock = $this->getMockBuilder(AggregationInterface::class) + ->getMockForAbstractClass(); + $this->connectionMock = $this->getMockBuilder(AdapterInterface::class) + ->getMockForAbstractClass(); + $this->selectMock = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->resourceMock->expects($this->any()) + ->method('getConnection') + ->willReturn($this->connectionMock); + $this->connectionMock->expects($this->once()) + ->method('select') + ->willReturn($this->selectMock); + + $this->model = (new ObjectManager($this))->getObject(Collection::class, [ + 'entityFactory' => $this->entityFactoryMock, + 'logger' => $this->loggerMock, + 'fetchStrategy' => $this->fetchStrategyMock, + 'eventManager' => $this->eventManagerMock, + 'mainTable' => null, + 'eventPrefix' => 'test_event_prefix', + 'eventObject' => 'test_event_object', + 'resourceModel' => null, + 'resource' => $this->resourceMock, + ]); + } + + /** + * @covers \Magento\Customer\Model\ResourceModel\Group\Grid\Collection::setSearchCriteria + * @covers \Magento\Customer\Model\ResourceModel\Group\Grid\Collection::getAggregations + */ + public function testSetGetAggregations() + { + $this->model->setAggregations($this->aggregationsMock); + $this->assertInstanceOf(AggregationInterface::class, $this->model->getAggregations()); + } + + /** + * @covers \Magento\Customer\Model\ResourceModel\Group\Grid\Collection::setSearchCriteria + */ + public function testSetSearchCriteria() + { + $this->assertEquals($this->model, $this->model->setSearchCriteria()); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/GroupActionsTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/GroupActionsTest.php new file mode 100644 index 0000000000000..7dbed062a57af --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/GroupActionsTest.php @@ -0,0 +1,133 @@ +createMock(ContextInterface::class); + + $processor = $this->getMockBuilder(Processor::class) + ->disableOriginalConstructor() + ->getMock(); + $context->expects(static::never()) + ->method('getProcessor') + ->willReturn($processor); + + $this->urlBuilder = $this->createMock(UrlInterface::class); + + $this->escaper = $this->getMockBuilder(Escaper::class) + ->disableOriginalConstructor() + ->setMethods(['escapeHtml']) + ->getMock(); + + $this->groupActions = $objectManager->getObject(GroupActions::class, [ + 'context' => $context, + 'urlBuilder' => $this->urlBuilder, + 'escaper' => $this->escaper, + ]); + } + + /** + * @covers \Magento\Customer\Ui\Component\Listing\Column\GroupActions::prepareDataSource + */ + public function testPrepareDataSource() + { + $groupId = 1; + $groupCode = 'group code'; + $items = [ + 'data' => [ + 'items' => [ + [ + 'customer_group_id' => $groupId, + 'customer_group_code' => $groupCode + ] + ] + ] + ]; + $name = 'item_name'; + $expectedItems = [ + [ + 'customer_group_id' => $groupId, + 'customer_group_code' => $groupCode, + $name => [ + 'edit' => [ + 'href' => 'test/url/edit', + 'label' => __('Edit'), + ], + 'delete' => [ + 'href' => 'test/url/delete', + 'label' => __('Delete'), + 'confirm' => [ + 'title' => __('Delete %1', $groupCode), + 'message' => __('Are you sure you want to delete a %1 record?', $groupCode) + ], + ] + ], + ] + ]; + + $this->escaper->expects(static::once()) + ->method('escapeHtml') + ->with($groupCode) + ->willReturn($groupCode); + + $this->urlBuilder->expects(static::exactly(2)) + ->method('getUrl') + ->willReturnMap( + [ + [ + GroupActions::URL_PATH_EDIT, + [ + 'id' => $groupId + ], + 'test/url/edit', + ], + [ + GroupActions::URL_PATH_DELETE, + [ + 'id' => $groupId + ], + 'test/url/delete', + ], + ] + ); + + $this->groupActions->setData('name', $name); + + $actual = $this->groupActions->prepareDataSource($items); + static::assertEquals($expectedItems, $actual['data']['items']); + } +} diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/GroupActions.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/GroupActions.php new file mode 100644 index 0000000000000..dac8f78500879 --- /dev/null +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/GroupActions.php @@ -0,0 +1,106 @@ +urlBuilder = $urlBuilder; + $this->escaper = $escaper; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + /** + * Prepare Data Source + * + * @param array $dataSource + * @return array + */ + public function prepareDataSource(array $dataSource) + { + if (isset($dataSource['data']['items'])) { + foreach ($dataSource['data']['items'] as & $item) { + if (isset($item['customer_group_id'])) { + $title = $this->escaper->escapeHtml($item['customer_group_code']); + $item[$this->getData('name')] = [ + 'edit' => [ + 'href' => $this->urlBuilder->getUrl( + static::URL_PATH_EDIT, + [ + 'id' => $item['customer_group_id'] + ] + ), + 'label' => __('Edit'), + ], + ]; + + // hide delete action for 'NOT LOGGED IN' group + if ($item['customer_group_id'] == 0 && $item['customer_group_code']) { + continue; + } + + $item[$this->getData('name')]['delete'] = [ + 'href' => $this->urlBuilder->getUrl( + static::URL_PATH_DELETE, + [ + 'id' => $item['customer_group_id'] + ] + ), + 'label' => __('Delete'), + 'confirm' => [ + 'title' => __('Delete %1', $title), + 'message' => __('Are you sure you want to delete a %1 record?', $title) + ] + ]; + } + } + } + + return $dataSource; + } +} diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml index 6df04c7f89656..7867bd992f3ac 100644 --- a/app/code/Magento/Customer/etc/di.xml +++ b/app/code/Magento/Customer/etc/di.xml @@ -215,6 +215,7 @@ Magento\Customer\Model\ResourceModel\Grid\Collection Magento\Customer\Model\ResourceModel\Online\Grid\Collection + Magento\Customer\Model\ResourceModel\Group\Grid\Collection @@ -420,4 +421,12 @@ + + + customer_group + customer_group_grid_collection + customer_group_collection + Magento\Customer\Model\ResourceModel\Group\Collection + + diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_group_index.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_group_index.xml index ecb64711bdb94..a65ef3cd395d0 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_group_index.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_group_index.xml @@ -8,48 +8,7 @@ - - - - customerGroupGrid - Magento\Customer\Model\ResourceModel\Group\Grid\ServiceCollection - type - asc - 1 - - - - - customer/*/edit - - getId - - - - - - ID - id - id - col-id - col-id - - - - - Group - code - - - - - Tax Class - tax_class_name - - - - - + diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_group_listing.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_group_listing.xml new file mode 100644 index 0000000000000..0787e0713aa9f --- /dev/null +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_group_listing.xml @@ -0,0 +1,76 @@ + + ++ + + customer_group_listing.customer_group_listing_data_source + + + + + + + customer_group_columns + + customer_group_listing.customer_group_listing_data_source + + + + + + customer_group_id + + + + Magento_Customer::group + + + id + customer_group_id + + + + + + + + + + + + + textRange + + asc + + + + + text + + + + + + + select + select + + + + + + customer_group_id + + + + From da5692cda81eff0d7dce889fac1c68ba4acd5ed7 Mon Sep 17 00:00:00 2001 From: serhii-balko Date: Fri, 16 Feb 2018 11:22:01 +0200 Subject: [PATCH 0033/2023] Fix depends field not working for radio elements #11539: case when depends field is not exist --- .../Product/Attribute/Edit/Tab/Front.php | 20 +++---------------- lib/web/mage/adminhtml/form.js | 12 ++++++----- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php index cc50dbde69ee3..a0ca53dce4f50 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php @@ -184,33 +184,19 @@ protected function _prepareForm() 'form_after', $this->getLayout()->createBlock( \Magento\Backend\Block\Widget\Form\Element\Dependence::class - )->addFieldMap( - "is_wysiwyg_enabled", - 'wysiwyg_enabled' )->addFieldMap( "is_html_allowed_on_front", 'html_allowed_on_front' )->addFieldMap( "frontend_input", 'frontend_input_type' - )->addFieldDependence( - 'wysiwyg_enabled', - 'frontend_input_type', - 'textarea' - )->addFieldDependence( - 'html_allowed_on_front', - 'wysiwyg_enabled', - '0' - ) - ->addFieldMap( + )->addFieldMap( "is_searchable", 'searchable' - ) - ->addFieldMap( + )->addFieldMap( "is_visible_in_advanced_search", 'advanced_search' - ) - ->addFieldDependence( + )->addFieldDependence( 'advanced_search', 'searchable', '1' diff --git a/lib/web/mage/adminhtml/form.js b/lib/web/mage/adminhtml/form.js index 2bd3ef86e8f90..c87c0fd05b0e2 100644 --- a/lib/web/mage/adminhtml/form.js +++ b/lib/web/mage/adminhtml/form.js @@ -456,12 +456,14 @@ define([ } else { values = valuesFrom[idFrom].values; fromId = $(idFrom + values[0]); - radioFrom = fromId ? $$('[name="' + fromId.name + '"]:checked') : []; - isInArray = radioFrom.length > 0 && values.indexOf(radioFrom[0].value) !== -1; - isNegative = valuesFrom[idFrom].negative; + if (fromId) { + radioFrom = $$('[name="' + fromId.name + '"]:checked'); + isInArray = radioFrom.length > 0 && values.indexOf(radioFrom[0].value) !== -1; + isNegative = valuesFrom[idFrom].negative; - if (!radioFrom || isInArray && isNegative || !isInArray && !isNegative) { - shouldShowUp = false; + if (!radioFrom || isInArray && isNegative || !isInArray && !isNegative) { + shouldShowUp = false; + } } } } From c48fc12cd0dab16ba1ca58e510ac2b676c6d8b6a Mon Sep 17 00:00:00 2001 From: Jeroen van Leusden Date: Wed, 6 Dec 2017 16:11:29 +0100 Subject: [PATCH 0034/2023] Move isAllowed method from AccessChangeQuoteControl to separate service --- .../Quote/Api/ChangeQuoteControlInterface.php | 23 ++++++++ .../Quote/Model/ChangeQuoteControl.php | 53 +++++++++++++++++++ .../Plugin/AccessChangeQuoteControl.php | 47 ++++------------ .../Plugin/AccessChangeQuoteControlTest.php | 38 +++++++++++-- app/code/Magento/Quote/etc/di.xml | 1 + 5 files changed, 121 insertions(+), 41 deletions(-) create mode 100644 app/code/Magento/Quote/Api/ChangeQuoteControlInterface.php create mode 100644 app/code/Magento/Quote/Model/ChangeQuoteControl.php diff --git a/app/code/Magento/Quote/Api/ChangeQuoteControlInterface.php b/app/code/Magento/Quote/Api/ChangeQuoteControlInterface.php new file mode 100644 index 0000000000000..ef6ecf746df76 --- /dev/null +++ b/app/code/Magento/Quote/Api/ChangeQuoteControlInterface.php @@ -0,0 +1,23 @@ +userContext = $userContext; + } + + /** + * {@inheritdoc} + */ + public function isAllowed(CartInterface $quote): bool + { + switch ($this->userContext->getUserType()) { + case UserContextInterface::USER_TYPE_CUSTOMER: + $isAllowed = ($quote->getCustomerId() == $this->userContext->getUserId()); + break; + case UserContextInterface::USER_TYPE_GUEST: + $isAllowed = ($quote->getCustomerId() === null); + break; + case UserContextInterface::USER_TYPE_ADMIN: + case UserContextInterface::USER_TYPE_INTEGRATION: + $isAllowed = true; + break; + default: + $isAllowed = false; + } + + return $isAllowed; + } +} diff --git a/app/code/Magento/Quote/Model/QuoteRepository/Plugin/AccessChangeQuoteControl.php b/app/code/Magento/Quote/Model/QuoteRepository/Plugin/AccessChangeQuoteControl.php index 3eff09faac1f5..79b518fc54534 100644 --- a/app/code/Magento/Quote/Model/QuoteRepository/Plugin/AccessChangeQuoteControl.php +++ b/app/code/Magento/Quote/Model/QuoteRepository/Plugin/AccessChangeQuoteControl.php @@ -3,10 +3,10 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Model\QuoteRepository\Plugin; -use Magento\Authorization\Model\UserContextInterface; -use Magento\Quote\Model\Quote; +use Magento\Quote\Api\ChangeQuoteControlInterface; use Magento\Framework\Exception\StateException; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Api\Data\CartInterface; @@ -17,24 +17,23 @@ class AccessChangeQuoteControl { /** - * @var UserContextInterface + * @var ChangeQuoteControlInterface $changeQuoteControl */ - private $userContext; + private $changeQuoteControl; /** - * @param UserContextInterface $userContext + * @param ChangeQuoteControlInterface $changeQuoteControl */ - public function __construct( - UserContextInterface $userContext - ) { - $this->userContext = $userContext; + public function __construct(ChangeQuoteControlInterface $changeQuoteControl) + { + $this->changeQuoteControl = $changeQuoteControl; } /** * Checks if change quote's customer id is allowed for current user. * * @param CartRepositoryInterface $subject - * @param Quote $quote + * @param CartInterface $quote * @throws StateException if Guest has customer_id or Customer's customer_id not much with user_id * or unknown user's type * @return void @@ -42,34 +41,8 @@ public function __construct( */ public function beforeSave(CartRepositoryInterface $subject, CartInterface $quote) { - if (!$this->isAllowed($quote)) { + if (! $this->changeQuoteControl->isAllowed($quote)) { throw new StateException(__("Invalid state change requested")); } } - - /** - * Checks if user is allowed to change the quote. - * - * @param Quote $quote - * @return bool - */ - private function isAllowed(Quote $quote) - { - switch ($this->userContext->getUserType()) { - case UserContextInterface::USER_TYPE_CUSTOMER: - $isAllowed = ($quote->getCustomerId() == $this->userContext->getUserId()); - break; - case UserContextInterface::USER_TYPE_GUEST: - $isAllowed = ($quote->getCustomerId() === null); - break; - case UserContextInterface::USER_TYPE_ADMIN: - case UserContextInterface::USER_TYPE_INTEGRATION: - $isAllowed = true; - break; - default: - $isAllowed = false; - } - - return $isAllowed; - } } diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteRepository/Plugin/AccessChangeQuoteControlTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteRepository/Plugin/AccessChangeQuoteControlTest.php index f330ebda17317..043e04319362d 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteRepository/Plugin/AccessChangeQuoteControlTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteRepository/Plugin/AccessChangeQuoteControlTest.php @@ -3,9 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Quote\Test\Unit\Model\QuoteRepository\Plugin; use Magento\Authorization\Model\UserContextInterface; +use Magento\Quote\Model\ChangeQuoteControl; use Magento\Quote\Model\QuoteRepository\Plugin\AccessChangeQuoteControl; use Magento\Quote\Model\Quote; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -34,6 +36,11 @@ class AccessChangeQuoteControlTest extends \PHPUnit\Framework\TestCase */ private $quoteRepositoryMock; + /** + * @var ChangeQuoteControl|MockObject + */ + private $changeQuoteControlMock; + protected function setUp() { $this->userContextMock = $this->getMockBuilder(UserContextInterface::class) @@ -50,15 +57,19 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); + $this->changeQuoteControlMock = $this->getMockBuilder(ChangeQuoteControl::class) + ->disableOriginalConstructor() + ->getMock(); + $objectManagerHelper = new ObjectManager($this); $this->accessChangeQuoteControl = $objectManagerHelper->getObject( AccessChangeQuoteControl::class, - ['userContext' => $this->userContextMock] + ['changeQuoteControl' => $this->changeQuoteControlMock] ); } /** - * User with role Customer and customer_id much with context user_id. + * User with role Customer and customer_id matches context user_id. */ public function testBeforeSaveForCustomer() { @@ -68,6 +79,9 @@ public function testBeforeSaveForCustomer() $this->userContextMock->method('getUserType') ->willReturn(UserContextInterface::USER_TYPE_CUSTOMER); + $this->changeQuoteControlMock->method('isAllowed') + ->willReturn(true); + $result = $this->accessChangeQuoteControl->beforeSave($this->quoteRepositoryMock, $this->quoteMock); $this->assertNull($result); @@ -81,11 +95,15 @@ public function testBeforeSaveForCustomer() */ public function testBeforeSaveException() { - $this->userContextMock->method('getUserType') - ->willReturn(UserContextInterface::USER_TYPE_CUSTOMER); $this->quoteMock->method('getCustomerId') ->willReturn(2); + $this->userContextMock->method('getUserType') + ->willReturn(UserContextInterface::USER_TYPE_CUSTOMER); + + $this->changeQuoteControlMock->method('isAllowed') + ->willReturn(false); + $this->accessChangeQuoteControl->beforeSave($this->quoteRepositoryMock, $this->quoteMock); } @@ -100,6 +118,9 @@ public function testBeforeSaveForAdmin() $this->userContextMock->method('getUserType') ->willReturn(UserContextInterface::USER_TYPE_ADMIN); + $this->changeQuoteControlMock->method('isAllowed') + ->willReturn(true); + $result = $this->accessChangeQuoteControl->beforeSave($this->quoteRepositoryMock, $this->quoteMock); $this->assertNull($result); @@ -116,6 +137,9 @@ public function testBeforeSaveForGuest() $this->userContextMock->method('getUserType') ->willReturn(UserContextInterface::USER_TYPE_GUEST); + $this->changeQuoteControlMock->method('isAllowed') + ->willReturn(true); + $result = $this->accessChangeQuoteControl->beforeSave($this->quoteRepositoryMock, $this->quoteMock); $this->assertNull($result); @@ -135,6 +159,9 @@ public function testBeforeSaveForGuestException() $this->userContextMock->method('getUserType') ->willReturn(UserContextInterface::USER_TYPE_GUEST); + $this->changeQuoteControlMock->method('isAllowed') + ->willReturn(false); + $this->accessChangeQuoteControl->beforeSave($this->quoteRepositoryMock, $this->quoteMock); } @@ -152,6 +179,9 @@ public function testBeforeSaveForUnknownUserTypeException() $this->userContextMock->method('getUserType') ->willReturn(10); + $this->changeQuoteControlMock->method('isAllowed') + ->willReturn(false); + $this->accessChangeQuoteControl->beforeSave($this->quoteRepositoryMock, $this->quoteMock); } } diff --git a/app/code/Magento/Quote/etc/di.xml b/app/code/Magento/Quote/etc/di.xml index 674e0eea46e97..aa6fafb5dd051 100644 --- a/app/code/Magento/Quote/etc/di.xml +++ b/app/code/Magento/Quote/etc/di.xml @@ -22,6 +22,7 @@ + From f5f3c761a42579a4b0b6b2cafc45c17e4e17248f Mon Sep 17 00:00:00 2001 From: Ankur Raiyani Date: Tue, 27 Feb 2018 12:44:20 +0530 Subject: [PATCH 0035/2023] Corrected Invoice Grid Column Subtotal value to copy from. Changed from sales_order to sales_invoice --- app/code/Magento/Sales/etc/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index 9de3f238d6a39..4e3d3a03af8f5 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -676,7 +676,7 @@ BillingAddressAggregator ShippingAddressAggregator sales_order.shipping_description - sales_order.base_subtotal + sales_invoice.base_subtotal sales_order.base_shipping_amount sales_invoice.base_grand_total sales_invoice.grand_total From 1268692cd2037f3d5df7f458bd91934c4272978a Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 24 Mar 2018 21:52:28 +0300 Subject: [PATCH 0036/2023] Fixed use config option for 'Enable Qty Increments' filed in product import --- .../Magento/CatalogImportExport/Model/Import/Product.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 58e2b13b192aa..502c5ce01f592 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -2636,7 +2636,10 @@ private function _setStockUseConfigFieldsValues($rowData) { $useConfigFields = []; foreach ($rowData as $key => $value) { - $useConfigName = self::INVENTORY_USE_CONFIG_PREFIX . $key; + $useConfigName = $key === 'enable_qty_increments' + ? 'use_config_enable_qty_inc' + : self::INVENTORY_USE_CONFIG_PREFIX . $key; + if (isset($this->defaultStockData[$key]) && isset($this->defaultStockData[$useConfigName]) && !empty($value) From 29431e958855ef19cc5289f8c86f39e2bc30f0a5 Mon Sep 17 00:00:00 2001 From: Alessandro Pagnin Date: Sun, 18 Feb 2018 16:08:58 +0100 Subject: [PATCH 0037/2023] Category collection now use getStoreId and not directly the store manager --- .../ResourceModel/Category/Collection.php | 2 +- .../Category/Collection/UrlRewriteTest.php | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php index 573914a13f6e5..46bb74513b59c 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php @@ -371,7 +371,7 @@ public function joinUrlRewrite() ['request_path'], sprintf( '{{table}}.is_autogenerated = 1 AND {{table}}.store_id = %d AND {{table}}.entity_type = \'%s\'', - $this->_storeManager->getStore()->getId(), + $this->getStoreId(), CategoryUrlRewriteGenerator::ENTITY_TYPE ), 'left' diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php new file mode 100644 index 0000000000000..5949b2951de03 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php @@ -0,0 +1,40 @@ +_model = $this->getMockBuilder( + \Magento\Catalog\Model\ResourceModel\Category\Collection::class + )->disableOriginalConstructor() + ->setMethodsExcept(['joinUrlRewrite', 'setStoreId', 'getStoreId']) + ->getMock(); + } + + + public function testStoreIdUsedByUrlRewrite() + { + $this->_model->expects($this->once()) + ->method('joinTable') + ->with( + $this->anything(), + $this->anything(), + $this->anything(), + $this->equalTo('{{table}}.is_autogenerated = 1 AND {{table}}.store_id = 100 AND {{table}}.entity_type = \'category\''), + $this->anything() + ); + $this->_model->setStoreId(100); + $this->_model->joinUrlRewrite(); + } +} From 47c8d54a84770286e9912b83cf11805d29bf40ea Mon Sep 17 00:00:00 2001 From: Alessandro Pagnin Date: Sun, 18 Feb 2018 17:06:42 +0100 Subject: [PATCH 0038/2023] code style fixes --- .../ResourceModel/Category/Collection/UrlRewriteTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php index 5949b2951de03..ea8cb51bf5e5e 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php @@ -22,16 +22,16 @@ protected function setUp() ->getMock(); } - public function testStoreIdUsedByUrlRewrite() { + $cond = '{{table}}.is_autogenerated = 1 AND {{table}}.store_id = 100 AND {{table}}.entity_type = \'category\''; $this->_model->expects($this->once()) ->method('joinTable') ->with( $this->anything(), $this->anything(), $this->anything(), - $this->equalTo('{{table}}.is_autogenerated = 1 AND {{table}}.store_id = 100 AND {{table}}.entity_type = \'category\''), + $this->equalTo($cond), $this->anything() ); $this->_model->setStoreId(100); From 2a014892b5d19c04f5462d2f00c3c7f5b557b0c2 Mon Sep 17 00:00:00 2001 From: Alessandro Pagnin Date: Sun, 18 Feb 2018 20:05:40 +0100 Subject: [PATCH 0039/2023] fixes to code style --- .../Category/Collection/UrlRewriteTest.php | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php index ea8cb51bf5e5e..7dec04fceaef6 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php @@ -15,9 +15,8 @@ class UrlRewriteTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->_model = $this->getMockBuilder( - \Magento\Catalog\Model\ResourceModel\Category\Collection::class - )->disableOriginalConstructor() + $this->_model = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Category\Collection::class) + ->disableOriginalConstructor() ->setMethodsExcept(['joinUrlRewrite', 'setStoreId', 'getStoreId']) ->getMock(); } @@ -26,14 +25,14 @@ public function testStoreIdUsedByUrlRewrite() { $cond = '{{table}}.is_autogenerated = 1 AND {{table}}.store_id = 100 AND {{table}}.entity_type = \'category\''; $this->_model->expects($this->once()) - ->method('joinTable') - ->with( - $this->anything(), - $this->anything(), - $this->anything(), - $this->equalTo($cond), - $this->anything() - ); + ->method('joinTable') + ->with( + $this->anything(), + $this->anything(), + $this->anything(), + $this->equalTo($cond), + $this->anything() + ); $this->_model->setStoreId(100); $this->_model->joinUrlRewrite(); } From 2d12dac1672aa4125b1012e454a8b58bb9ee9b73 Mon Sep 17 00:00:00 2001 From: Alessandro Pagnin Date: Sun, 18 Mar 2018 23:26:09 +0100 Subject: [PATCH 0040/2023] add integration test --- .../ResourceModel/Category/CollectionTest.php | 62 +++++++++++++++++++ .../_files/category_multiple_stores.php | 61 ++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php new file mode 100644 index 0000000000000..7d2d5d8e443a7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php @@ -0,0 +1,62 @@ +collection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\ResourceModel\Category\Collection::class + ); + } + + protected function setDown() { + /* Refresh stores memory cache after store deletion */ + \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Store\Model\StoreManagerInterface::class + )->reinitStores(); + } + + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php + */ + public function testJoinUrlRewriteOnDefault() + { + $categories = $this->collection->joinUrlRewrite()->addPathFilter('1/2/3'); + $this->assertCount(1, $categories); + /** @var $category \Magento\Catalog\Model\Category */ + $category = $categories->getFirstItem(); + $this->assertStringEndsWith('category.html', $category->getUrl()); + } + + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php + */ + public function testJoinUrlRewriteNotOnDefaultStore() + { + $store = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); + $storeId = $store->load('second_category_store', 'code')->getId(); + $categories = $this->collection->setStoreId($storeId)->joinUrlRewrite()->addPathFilter('1/2/3'); + $this->assertCount(1, $categories); + /** @var $category \Magento\Catalog\Model\Category */ + $category = $categories->getFirstItem(); + $this->assertStringEndsWith('category-3-on-2.html', $category->getUrl()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php new file mode 100644 index 0000000000000..c6590bb6a0f9f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php @@ -0,0 +1,61 @@ +create( + \Magento\Catalog\Model\CategoryFactory::class +); +/** @var \Magento\Catalog\Model\CategoryRepository $repository */ +$repository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\CategoryRepository::class +); +/** @var \Magento\Store\Model\StoreManagerInterface $storeManager */ +$storeManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Store\Model\StoreManagerInterface::class +); +/** @var \Magento\Store\Model\Store $store */ +$store = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); +if (!$store->load('second_category_store', 'code')->getId()) { + $websiteId = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Store\Model\StoreManagerInterface::class + )->getWebsite()->getId(); + $groupId = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Store\Model\StoreManagerInterface::class + )->getWebsite()->getDefaultGroupId(); + $store->setCode( + 'second_category_store' + )->setWebsiteId( + $websiteId + )->setGroupId( + $groupId + )->setName( + 'Fixture Store' + )->setSortOrder( + 10 + )->setIsActive( + 1 + ); + $store->save(); +} + +/* Refresh stores memory cache */ +\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Store\Model\StoreManagerInterface::class +)->reinitStores(); + +/** @var \Magento\Catalog\Model\Category $newCategory */ +$newCategory = $factory->create(); +$newCategory + ->setName('Category') + ->setParentId(2) + ->setLevel(2) + ->setPath('1/2/3') + ->setAvailableSortBy('name') + ->setDefaultSortBy('name') + ->setIsActive(true) + ->setPosition(1); +$repository->save($newCategory); +$currentStoreId = $storeManager->getStore()->getId(); +$storeManager->setCurrentStore($storeManager->getStore($store->getId())); +$newCategory + ->setUrlKey('category-3-on-2'); +$repository->save($newCategory); +$storeManager->setCurrentStore($storeManager->getStore($currentStoreId)); \ No newline at end of file From 8a097fc1a83acd63b702661e12bcb10a00b36630 Mon Sep 17 00:00:00 2001 From: Alessandro Pagnin Date: Sun, 18 Mar 2018 23:47:39 +0100 Subject: [PATCH 0041/2023] fix to code style --- .../Catalog/Model/ResourceModel/Category/CollectionTest.php | 6 ++++-- .../Model/ResourceModel/_files/category_multiple_stores.php | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php index 7d2d5d8e443a7..dd1a6eefbe532 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php @@ -23,7 +23,8 @@ protected function setUp() ); } - protected function setDown() { + protected function setDown() + { /* Refresh stores memory cache after store deletion */ \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( \Magento\Store\Model\StoreManagerInterface::class @@ -51,7 +52,8 @@ public function testJoinUrlRewriteOnDefault() */ public function testJoinUrlRewriteNotOnDefaultStore() { - $store = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); + $store = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Store\Model\Store::class); $storeId = $store->load('second_category_store', 'code')->getId(); $categories = $this->collection->setStoreId($storeId)->joinUrlRewrite()->addPathFilter('1/2/3'); $this->assertCount(1, $categories); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php index c6590bb6a0f9f..330a682106d89 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php @@ -58,4 +58,4 @@ $newCategory ->setUrlKey('category-3-on-2'); $repository->save($newCategory); -$storeManager->setCurrentStore($storeManager->getStore($currentStoreId)); \ No newline at end of file +$storeManager->setCurrentStore($storeManager->getStore($currentStoreId)); From af3804ac4e846d42593ab73df3535a24d4ff9f8b Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Mon, 26 Mar 2018 16:23:03 +0300 Subject: [PATCH 0042/2023] magento/magento2#13716 --- .../Category/Collection/UrlRewriteTest.php | 10 +++++----- .../Model/ResourceModel/Category/CollectionTest.php | 2 +- .../ResourceModel/_files/category_multiple_stores.php | 9 +++++++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php index 7dec04fceaef6..b1f5f17f64a59 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php @@ -11,11 +11,11 @@ class UrlRewriteTest extends \PHPUnit\Framework\TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_model; + private $model; protected function setUp() { - $this->_model = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Category\Collection::class) + $this->model = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Category\Collection::class) ->disableOriginalConstructor() ->setMethodsExcept(['joinUrlRewrite', 'setStoreId', 'getStoreId']) ->getMock(); @@ -24,7 +24,7 @@ protected function setUp() public function testStoreIdUsedByUrlRewrite() { $cond = '{{table}}.is_autogenerated = 1 AND {{table}}.store_id = 100 AND {{table}}.entity_type = \'category\''; - $this->_model->expects($this->once()) + $this->model->expects($this->once()) ->method('joinTable') ->with( $this->anything(), @@ -33,7 +33,7 @@ public function testStoreIdUsedByUrlRewrite() $this->equalTo($cond), $this->anything() ); - $this->_model->setStoreId(100); - $this->_model->joinUrlRewrite(); + $this->model->setStoreId(100); + $this->model->joinUrlRewrite(); } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php index dd1a6eefbe532..7e26cdb921f39 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Category/CollectionTest.php @@ -10,7 +10,7 @@ class CollectionTest extends \PHPUnit\Framework\TestCase /** * @var \Magento\Catalog\Model\ResourceModel\Category\Collection */ - protected $collection; + private $collection; /** * Sets up the fixture, for example, opens a network connection. diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php index 330a682106d89..90bf630000e72 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/category_multiple_stores.php @@ -1,4 +1,9 @@ create( \Magento\Catalog\Model\CategoryFactory::class @@ -20,6 +25,7 @@ $groupId = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( \Magento\Store\Model\StoreManagerInterface::class )->getWebsite()->getDefaultGroupId(); + $store->setCode( 'second_category_store' )->setWebsiteId( @@ -55,7 +61,6 @@ $repository->save($newCategory); $currentStoreId = $storeManager->getStore()->getId(); $storeManager->setCurrentStore($storeManager->getStore($store->getId())); -$newCategory - ->setUrlKey('category-3-on-2'); +$newCategory->setUrlKey('category-3-on-2'); $repository->save($newCategory); $storeManager->setCurrentStore($storeManager->getStore($currentStoreId)); From 474fac46a9d70bb26fca8edbb8a093de989a28e8 Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya Date: Tue, 27 Mar 2018 13:21:29 +0530 Subject: [PATCH 0043/2023] Removed unused translation for comment tag --- app/code/Magento/Analytics/etc/adminhtml/system.xml | 4 ++-- app/code/Magento/Catalog/etc/adminhtml/system.xml | 6 +++--- app/code/Magento/Sales/etc/adminhtml/system.xml | 6 +++--- app/code/Magento/Swatches/etc/adminhtml/system.xml | 4 ++-- app/code/Magento/Ups/etc/adminhtml/system.xml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Analytics/etc/adminhtml/system.xml b/app/code/Magento/Analytics/etc/adminhtml/system.xml index 889517e629e04..4e21648d00ce8 100644 --- a/app/code/Magento/Analytics/etc/adminhtml/system.xml +++ b/app/code/Magento/Analytics/etc/adminhtml/system.xml @@ -17,14 +17,14 @@ Your reports can be accessed securely on a personalized dashboard outside of the admin panel by clicking on the "Go to Advanced Reporting" link.
For more information, see our terms and conditions.]]> - + Magento\Config\Model\Config\Source\Enabledisable Magento\Analytics\Model\Config\Backend\Enabled Magento\Analytics\Block\Adminhtml\System\Config\SubscriptionStatusLabel analytics/subscription/enabled - + Magento\Analytics\Block\Adminhtml\System\Config\CollectionTimeLabel Magento\Analytics\Model\Config\Backend\CollectionTime diff --git a/app/code/Magento/Catalog/etc/adminhtml/system.xml b/app/code/Magento/Catalog/etc/adminhtml/system.xml index 2ce40386f0553..a65429e65973c 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/system.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/system.xml @@ -36,10 +36,10 @@ - + - + @@ -83,7 +83,7 @@ Magento\Catalog\Model\Indexer\Product\Flat\System\Config\Mode Magento\Config\Model\Config\Source\Yesno - + Magento\Catalog\Model\Config\Source\ListSort diff --git a/app/code/Magento/Sales/etc/adminhtml/system.xml b/app/code/Magento/Sales/etc/adminhtml/system.xml index 6261353332cef..9d6d11d56c81f 100644 --- a/app/code/Magento/Sales/etc/adminhtml/system.xml +++ b/app/code/Magento/Sales/etc/adminhtml/system.xml @@ -106,15 +106,15 @@ We'll use the default error above if you leave this empty. - + - + Magento\Config\Model\Config\Source\Yesno Improves dashboard performance but provides non-realtime data. - + diff --git a/app/code/Magento/Swatches/etc/adminhtml/system.xml b/app/code/Magento/Swatches/etc/adminhtml/system.xml index 7c61c240f9965..219fa9c913e5c 100644 --- a/app/code/Magento/Swatches/etc/adminhtml/system.xml +++ b/app/code/Magento/Swatches/etc/adminhtml/system.xml @@ -9,10 +9,10 @@
- + - + Magento\Config\Model\Config\Source\Yesno diff --git a/app/code/Magento/Ups/etc/adminhtml/system.xml b/app/code/Magento/Ups/etc/adminhtml/system.xml index 255039e6499cc..ff501e484f3ee 100644 --- a/app/code/Magento/Ups/etc/adminhtml/system.xml +++ b/app/code/Magento/Ups/etc/adminhtml/system.xml @@ -106,7 +106,7 @@ Magento\Config\Model\Config\Source\Yesno - + Magento\Ups\Model\Config\Source\Unitofmeasure From f5e429d52724795c804498a87884e84619149ea5 Mon Sep 17 00:00:00 2001 From: Bartek Igielski Date: Tue, 27 Mar 2018 16:20:57 +0200 Subject: [PATCH 0044/2023] Fixed extends and removed unnecessary variables --- .../web/css/source/module/checkout/_tooltip.less | 3 +-- .../Magento/blank/Magento_Sales/web/css/source/_module.less | 2 +- .../frontend/Magento/blank/web/css/source/_extends.less | 2 +- .../blank/web/css/source/components/_modals_extend.less | 5 ++--- .../frontend/Magento/luma/web/css/source/_extends.less | 2 +- .../luma/web/css/source/components/_modals_extend.less | 5 ++--- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less index cf84f34279086..273f626ec03d6 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less @@ -8,7 +8,6 @@ // _____________________________________________ @checkout-tooltip__hover__z-index: @tooltip__z-index; -@checkout-tooltip-breakpoint__screen-m: @modal-popup-breakpoint-screen__m; @checkout-tooltip-icon-arrow__font-size: 10px; @checkout-tooltip-icon-arrow__left: -( @checkout-tooltip-content__padding + @checkout-tooltip-icon-arrow__font-size - @checkout-tooltip-content__border-width); @@ -138,7 +137,7 @@ } } -.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @checkout-tooltip-breakpoint__screen-m) { +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { .field-tooltip { .field-tooltip-content { &:extend(.abs-checkout-tooltip-content-position-top-mobile all); diff --git a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_module.less index 1ea1e2c483d0b..3847393a2f046 100644 --- a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_module.less @@ -262,7 +262,7 @@ } .toolbar { - &:extend(.abs-add-clearfix-desktop all); + &:extend(.abs-add-clearfix-mobile all); .pages { float: right; diff --git a/app/design/frontend/Magento/blank/web/css/source/_extends.less b/app/design/frontend/Magento/blank/web/css/source/_extends.less index d4bede1279602..a36934111eb06 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_extends.less +++ b/app/design/frontend/Magento/blank/web/css/source/_extends.less @@ -1233,7 +1233,7 @@ } } -.media-width(@extremum, @break) when (@extremum = 'max') and (@break = (@screen__m + 1)) { +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { .abs-checkout-tooltip-content-position-top-mobile { @abs-checkout-tooltip-content-position-top(); } diff --git a/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less index d324bbeac598f..d76630b5cea47 100644 --- a/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less +++ b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less @@ -16,7 +16,6 @@ @modal-popup-title__font-size: 26px; @modal-popup-title-mobile__font-size: @font-size__base; -@modal-popup-breakpoint-screen__m: @screen__m; @modal-slide__first__indent-left: 44px; @modal-slide-mobile__background-color: @color-gray-light01; @@ -149,7 +148,7 @@ } } -.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @modal-popup-breakpoint-screen__m) { +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { .modal-popup { &.modal-slide { .modal-inner-wrap[class] { @@ -180,7 +179,7 @@ // Desktop // _____________________________________________ -.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @modal-popup-breakpoint-screen__m) { +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .modal-popup { &.modal-slide { .modal-footer { diff --git a/app/design/frontend/Magento/luma/web/css/source/_extends.less b/app/design/frontend/Magento/luma/web/css/source/_extends.less index 602ed44d5a44d..760ec9ed861a9 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_extends.less +++ b/app/design/frontend/Magento/luma/web/css/source/_extends.less @@ -1681,7 +1681,7 @@ } } -.media-width(@extremum, @break) when (@extremum = 'max') and (@break = (@screen__m + 1)) { +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { .abs-checkout-tooltip-content-position-top-mobile { @abs-checkout-tooltip-content-position-top(); } diff --git a/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less b/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less index b3165a41964e5..e90d312aa7801 100644 --- a/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less +++ b/app/design/frontend/Magento/luma/web/css/source/components/_modals_extend.less @@ -16,7 +16,6 @@ @modal-popup-title__font-size: 26px; @modal-popup-title-mobile__font-size: @font-size__base; -@modal-popup-breakpoint-screen__m: @screen__m; @modal-slide__first__indent-left: 44px; @modal-slide-mobile__background-color: @color-gray-light01; @@ -148,7 +147,7 @@ } } -.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @modal-popup-breakpoint-screen__m) { +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { .modal-popup { &.modal-slide { .modal-inner-wrap[class] { @@ -179,7 +178,7 @@ // Desktop // _____________________________________________ -.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @modal-popup-breakpoint-screen__m) { +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .modal-popup { &.modal-slide { .modal-footer { From 23048d319f208f275a93cad13ef382a91488e86f Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya Date: Tue, 27 Mar 2018 13:21:29 +0530 Subject: [PATCH 0045/2023] Removed unused translation for comment tag --- app/code/Magento/Analytics/etc/adminhtml/system.xml | 4 ++-- app/code/Magento/Catalog/etc/adminhtml/system.xml | 6 +++--- app/code/Magento/Sales/etc/adminhtml/system.xml | 6 +++--- app/code/Magento/Swatches/etc/adminhtml/system.xml | 4 ++-- app/code/Magento/Ups/etc/adminhtml/system.xml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Analytics/etc/adminhtml/system.xml b/app/code/Magento/Analytics/etc/adminhtml/system.xml index 889517e629e04..4e21648d00ce8 100644 --- a/app/code/Magento/Analytics/etc/adminhtml/system.xml +++ b/app/code/Magento/Analytics/etc/adminhtml/system.xml @@ -17,14 +17,14 @@ Your reports can be accessed securely on a personalized dashboard outside of the admin panel by clicking on the "Go to Advanced Reporting" link.
For more information, see our terms and conditions.]]> - + Magento\Config\Model\Config\Source\Enabledisable Magento\Analytics\Model\Config\Backend\Enabled Magento\Analytics\Block\Adminhtml\System\Config\SubscriptionStatusLabel analytics/subscription/enabled - + Magento\Analytics\Block\Adminhtml\System\Config\CollectionTimeLabel Magento\Analytics\Model\Config\Backend\CollectionTime diff --git a/app/code/Magento/Catalog/etc/adminhtml/system.xml b/app/code/Magento/Catalog/etc/adminhtml/system.xml index 2ce40386f0553..a65429e65973c 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/system.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/system.xml @@ -36,10 +36,10 @@
- + - + @@ -83,7 +83,7 @@ Magento\Catalog\Model\Indexer\Product\Flat\System\Config\Mode Magento\Config\Model\Config\Source\Yesno - + Magento\Catalog\Model\Config\Source\ListSort diff --git a/app/code/Magento/Sales/etc/adminhtml/system.xml b/app/code/Magento/Sales/etc/adminhtml/system.xml index 6261353332cef..9d6d11d56c81f 100644 --- a/app/code/Magento/Sales/etc/adminhtml/system.xml +++ b/app/code/Magento/Sales/etc/adminhtml/system.xml @@ -106,15 +106,15 @@ We'll use the default error above if you leave this empty. - + - + Magento\Config\Model\Config\Source\Yesno Improves dashboard performance but provides non-realtime data. - + diff --git a/app/code/Magento/Swatches/etc/adminhtml/system.xml b/app/code/Magento/Swatches/etc/adminhtml/system.xml index 7c61c240f9965..219fa9c913e5c 100644 --- a/app/code/Magento/Swatches/etc/adminhtml/system.xml +++ b/app/code/Magento/Swatches/etc/adminhtml/system.xml @@ -9,10 +9,10 @@
- + - + Magento\Config\Model\Config\Source\Yesno diff --git a/app/code/Magento/Ups/etc/adminhtml/system.xml b/app/code/Magento/Ups/etc/adminhtml/system.xml index 255039e6499cc..ff501e484f3ee 100644 --- a/app/code/Magento/Ups/etc/adminhtml/system.xml +++ b/app/code/Magento/Ups/etc/adminhtml/system.xml @@ -106,7 +106,7 @@ Magento\Config\Model\Config\Source\Yesno - + Magento\Ups\Model\Config\Source\Unitofmeasure From e7cca96ebc2b88c88f569726838bddb9bab22245 Mon Sep 17 00:00:00 2001 From: Freek Vandeursen Date: Thu, 29 Mar 2018 10:29:52 +0200 Subject: [PATCH 0046/2023] Fix bug with retry connect and custom db port --- lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php index 97377c94ca91a..e3dd5d5d6b57a 100644 --- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php +++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php @@ -549,6 +549,14 @@ protected function _query($sql, $bind = []) $retry = true; $triesCount++; $this->closeConnection(); + + /** + * _connect() function does not allow port parameter, so put the port back with the host + */ + if (!empty($this->_config['port'])) { + $this->_config['host'] = implode(':', [$this->_config['host'], $this->_config['port']]); + } + $this->_connect(); } From 9fcc4dacac4c42090a10fe15218a3140f0863fd2 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 29 Mar 2018 12:15:25 +0300 Subject: [PATCH 0047/2023] MAGETWO-89540: Static CompilerTest doesn't understand nullable type hint --- .../Framework/Code/Reader/SourceArgumentsReaderTest.php | 2 ++ .../Code/Reader/_files/SourceArgumentsReaderTest.php.sample | 2 ++ .../Magento/Framework/Code/Reader/SourceArgumentsReader.php | 5 ++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/SourceArgumentsReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/SourceArgumentsReaderTest.php index d1b22e853ce1d..035033445ca6f 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/SourceArgumentsReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/SourceArgumentsReaderTest.php @@ -44,6 +44,8 @@ public function getConstructorArgumentTypesDataProvider() '\Imported\Name\Space\ClassName\Under\Test', '\Imported\Name\Space\ClassName', '\Some\Testing\Name\Space\Test', + '\Exception', + '\Imported\Name\Space\ClassName', 'array', '' ], diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/_files/SourceArgumentsReaderTest.php.sample b/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/_files/SourceArgumentsReaderTest.php.sample index 47c059de2034b..6d9322f8c8971 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/_files/SourceArgumentsReaderTest.php.sample +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/_files/SourceArgumentsReaderTest.php.sample @@ -19,6 +19,8 @@ class AnotherSimpleClass ClassName\Under\Test $itemFive, ClassName $itemSix, Test $itemSeven, + ?\Exception $optionalException, + ?ClassName $optionalWithDefaultValue = null, array $itemEight = [], $itemNine = 'test' ) { diff --git a/lib/internal/Magento/Framework/Code/Reader/SourceArgumentsReader.php b/lib/internal/Magento/Framework/Code/Reader/SourceArgumentsReader.php index 0fb3825d240a1..5aabbf1b466a1 100644 --- a/lib/internal/Magento/Framework/Code/Reader/SourceArgumentsReader.php +++ b/lib/internal/Magento/Framework/Code/Reader/SourceArgumentsReader.php @@ -56,7 +56,7 @@ public function getConstructorArgumentTypes(\ReflectionClass $class, $inherited $source = ' &$argument) { $argument = $this->removeToken($argument, '='); $argument = $this->removeToken($argument, '&'); + if (mb_strpos($argument, '?') === 0) { + $argument = mb_substr($argument, 1); + } $argument = $this->namespaceResolver->resolveNamespace($argument, $availableNamespaces); } unset($argument); From 1b1e15e2be5893eea09dd6f9fc8778bb1cbb9942 Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya Date: Thu, 29 Mar 2018 15:29:26 +0530 Subject: [PATCH 0048/2023] Removed extra slash from comment block --- .../Magento/InstantPurchase/CustomerData/InstantPurchase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/InstantPurchase/CustomerData/InstantPurchase.php b/app/code/Magento/InstantPurchase/CustomerData/InstantPurchase.php index 3d9c06e76ea08..7ded5373dc735 100644 --- a/app/code/Magento/InstantPurchase/CustomerData/InstantPurchase.php +++ b/app/code/Magento/InstantPurchase/CustomerData/InstantPurchase.php @@ -30,7 +30,7 @@ class InstantPurchase implements SectionSourceInterface private $customerSession; /** - * @var StoreManagerInterface\ + * @var StoreManagerInterface */ private $storeManager; From ef4ca85e70465aad5dffbca316fdf555ffac5549 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Thu, 29 Mar 2018 14:43:17 +0300 Subject: [PATCH 0049/2023] MAGETWO-89540: Static CompilerTest doesn't understand nullable type hint --- .../Code/Reader/SourceArgumentsReaderTest.php | 1 + .../SourceArgumentsReaderTest.php.sample | 1 + .../Code/Reader/SourceArgumentsReader.php | 81 ++++++++----------- 3 files changed, 37 insertions(+), 46 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/SourceArgumentsReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/SourceArgumentsReaderTest.php index 035033445ca6f..103df9f570a2a 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/SourceArgumentsReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/SourceArgumentsReaderTest.php @@ -45,6 +45,7 @@ public function getConstructorArgumentTypesDataProvider() '\Imported\Name\Space\ClassName', '\Some\Testing\Name\Space\Test', '\Exception', + '', '\Imported\Name\Space\ClassName', 'array', '' diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/_files/SourceArgumentsReaderTest.php.sample b/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/_files/SourceArgumentsReaderTest.php.sample index 6d9322f8c8971..5efe7837e7a3a 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/_files/SourceArgumentsReaderTest.php.sample +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/Reader/_files/SourceArgumentsReaderTest.php.sample @@ -20,6 +20,7 @@ class AnotherSimpleClass ClassName $itemSix, Test $itemSeven, ?\Exception $optionalException, + $defaultString = '$default),value;', ?ClassName $optionalWithDefaultValue = null, array $itemEight = [], $itemNine = 'test' diff --git a/lib/internal/Magento/Framework/Code/Reader/SourceArgumentsReader.php b/lib/internal/Magento/Framework/Code/Reader/SourceArgumentsReader.php index 5aabbf1b466a1..31243f6ad98f9 100644 --- a/lib/internal/Magento/Framework/Code/Reader/SourceArgumentsReader.php +++ b/lib/internal/Magento/Framework/Code/Reader/SourceArgumentsReader.php @@ -37,8 +37,10 @@ public function __construct(NamespaceResolver $namespaceResolver = null) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ - public function getConstructorArgumentTypes(\ReflectionClass $class, $inherited = false) - { + public function getConstructorArgumentTypes( + \ReflectionClass $class, + $inherited = false + ) { $output = [null]; if (!$class->getFileName() || false == $class->hasMethod( '__construct' @@ -46,52 +48,37 @@ public function getConstructorArgumentTypes(\ReflectionClass $class, $inherited ) { return $output; } - $reflectionConstructor = $class->getConstructor(); - $fileContent = file($class->getFileName()); - $availableNamespaces = $this->namespaceResolver->getImportedNamespaces($fileContent); - $availableNamespaces[0] = $class->getNamespaceName(); - $constructorStartLine = $reflectionConstructor->getStartLine() - 1; - $constructorEndLine = $reflectionConstructor->getEndLine(); - $fileContent = array_slice($fileContent, $constructorStartLine, $constructorEndLine - $constructorStartLine); - $source = ' $argument]; - } - unset($argument); - $arguments = array_filter($arguments, function ($token) { - $blacklist = [T_VARIABLE, T_WHITESPACE]; - if (isset($token[0]) && in_array($token[0], $blacklist)) { - return false; + //Reading parameters' types. + $params = $class->getConstructor()->getParameters(); + /** @var string[] $types */ + $types = []; + foreach ($params as $param) { + //For the sake of backward compatibility. + $typeName = ''; + if ($param->isArray()) { + //For the sake of backward compatibility. + $typeName = 'array'; + } else { + try { + $paramClass = $param->getClass(); + if ($paramClass) { + $typeName = '\\' .$paramClass->getName(); + } + } catch (\ReflectionException $exception) { + //If there's a problem loading a class then ignore it and + //just return it's name. + $typeName = '\\' .$param->getType()->getName(); + } } - return true; - }); - $arguments = array_map(function ($element) { - return $element[1]; - }, $arguments); - $arguments = array_values($arguments); - $arguments = implode('', $arguments); - if (empty($arguments)) { - return $output; + $types[] = $typeName; } - $arguments = explode(',', $arguments); - foreach ($arguments as $key => &$argument) { - $argument = $this->removeToken($argument, '='); - $argument = $this->removeToken($argument, '&'); - if (mb_strpos($argument, '?') === 0) { - $argument = mb_substr($argument, 1); - } - $argument = $this->namespaceResolver->resolveNamespace($argument, $availableNamespaces); + if (!$types) { + //For the sake of backward compatibility. + $types = [null]; } - unset($argument); - return $arguments; + + return $types; } /** @@ -101,7 +88,7 @@ public function getConstructorArgumentTypes(\ReflectionClass $class, $inherited * @param array $availableNamespaces * @return string * @deprecated 100.2.0 - * @see \Magento\Framework\Code\Reader\NamespaceResolver::resolveNamespace + * @see getConstructorArgumentTypes */ protected function resolveNamespaces($argument, $availableNamespaces) { @@ -114,6 +101,8 @@ protected function resolveNamespaces($argument, $availableNamespaces) * @param string $argument * @param string $token * @return string + * + * @deprecated Not used anymore. */ protected function removeToken($argument, $token) { @@ -130,7 +119,7 @@ protected function removeToken($argument, $token) * @param array $file * @return array * @deprecated 100.2.0 - * @see \Magento\Framework\Code\Reader\NamespaceResolver::getImportedNamespaces + * @see getConstructorArgumentTypes */ protected function getImportedNamespaces(array $file) { From b5aac653b88eb280d5e90685d3925cdc26a8c2db Mon Sep 17 00:00:00 2001 From: NamrataChangani <37930646+NamrataChangani@users.noreply.github.com> Date: Fri, 30 Mar 2018 18:18:00 +0530 Subject: [PATCH 0050/2023] Correct function return statement. --- app/code/Magento/Security/Model/AdminSessionInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Security/Model/AdminSessionInfo.php b/app/code/Magento/Security/Model/AdminSessionInfo.php index 1aeb1b671c5cf..77d864965baca 100644 --- a/app/code/Magento/Security/Model/AdminSessionInfo.php +++ b/app/code/Magento/Security/Model/AdminSessionInfo.php @@ -164,7 +164,7 @@ public function isOtherSessionsTerminated() * Setter for isOtherSessionsTerminated * * @param bool $isOtherSessionsTerminated - * @return this + * @return $this * @since 100.1.0 */ public function setIsOtherSessionsTerminated($isOtherSessionsTerminated) From 22345400251086949794e8cccf64aa09788f9075 Mon Sep 17 00:00:00 2001 From: NamrataChangani <37930646+NamrataChangani@users.noreply.github.com> Date: Fri, 30 Mar 2018 18:18:47 +0530 Subject: [PATCH 0051/2023] Correct function return statement. --- app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote.php index 15f87931886c8..55e1d319cc776 100644 --- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote.php +++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote.php @@ -74,7 +74,7 @@ protected function _initRule() /** * Initiate action * - * @return this + * @return $this */ protected function _initAction() { From 581c8a19ad4013f21866cc506a26341e853efaf1 Mon Sep 17 00:00:00 2001 From: Sergey Date: Fri, 30 Mar 2018 23:03:40 +0300 Subject: [PATCH 0052/2023] [Improvement] Implement design theme grid on ui component --- .../Adminhtml/System/Design/Theme/Index.php | 1 + .../ResourceModel/Theme/Grid/Collection.php | 133 +++++++++++++++++- .../Theme/Grid/CollectionTest.php | 128 +++++++++++++++++ app/code/Magento/Theme/etc/di.xml | 9 ++ app/code/Magento/Theme/i18n/en_US.csv | 1 + .../adminhtml_system_design_theme_index.xml | 4 +- .../ui_component/design_theme_listing.xml | 66 +++++++++ 7 files changed, 338 insertions(+), 4 deletions(-) create mode 100644 app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php create mode 100644 app/code/Magento/Theme/view/adminhtml/ui_component/design_theme_listing.xml diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Index.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Index.php index 4bae57f80209e..d51fd658075f1 100644 --- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Index.php +++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Index.php @@ -21,6 +21,7 @@ public function execute() { $this->_view->loadLayout(); $this->_setActiveMenu('Magento_Theme::system_design_theme'); + $this->_view->getLayout()->getBlock('page.title')->setPageTitle('Themes'); $this->_view->renderLayout(); } } diff --git a/app/code/Magento/Theme/Model/ResourceModel/Theme/Grid/Collection.php b/app/code/Magento/Theme/Model/ResourceModel/Theme/Grid/Collection.php index f708b3c7889f3..841f4fb8c3e63 100644 --- a/app/code/Magento/Theme/Model/ResourceModel/Theme/Grid/Collection.php +++ b/app/code/Magento/Theme/Model/ResourceModel/Theme/Grid/Collection.php @@ -5,11 +5,62 @@ */ namespace Magento\Theme\Model\ResourceModel\Theme\Grid; +use Magento\Theme\Model\ResourceModel\Theme\Collection as ThemeCollection; +use Magento\Framework\Api\Search\SearchResultInterface; +use Magento\Framework\Search\AggregationInterface; + /** * Theme grid collection */ -class Collection extends \Magento\Theme\Model\ResourceModel\Theme\Collection +class Collection extends ThemeCollection implements SearchResultInterface { + /** + * @var AggregationInterface + */ + protected $aggregations; + + /** + * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory + * @param \Psr\Log\LoggerInterface $logger + * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy + * @param \Magento\Framework\Event\ManagerInterface $eventManager + * @param string $mainTable + * @param string $eventPrefix + * @param string $eventObject + * @param string $resourceModel + * @param string $model + * @param \Magento\Framework\DB\Adapter\AdapterInterface|string|null $connection + * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory, + \Psr\Log\LoggerInterface $logger, + \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, + \Magento\Framework\Event\ManagerInterface $eventManager, + $mainTable, + $eventPrefix, + $eventObject, + $resourceModel, + $model = \Magento\Framework\View\Element\UiComponent\DataProvider\Document::class, + $connection = null, + \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null + ) { + parent::__construct( + $entityFactory, + $logger, + $fetchStrategy, + $eventManager, + $connection, + $resource + ); + $this->_eventPrefix = $eventPrefix; + $this->_eventObject = $eventObject; + $this->_init($model, $resourceModel); + $this->setMainTable($mainTable); + } + /** * Add area filter * @@ -19,6 +70,86 @@ protected function _initSelect() { \Magento\Theme\Model\ResourceModel\Theme\Collection::_initSelect(); $this->filterVisibleThemes()->addAreaFilter(\Magento\Framework\App\Area::AREA_FRONTEND)->addParentTitle(); + $this + ->addFilterToMap('theme_id', 'main_table.theme_id') + ->addFilterToMap('theme_title', 'main_table.theme_title') + ->addFilterToMap('theme_path', 'main_table.theme_path') + ->addFilterToMap('parent_theme_title', 'parent.theme_title') + ; + return $this; + } + + /** + * @return AggregationInterface + */ + public function getAggregations() + { + return $this->aggregations; + } + + /** + * @param AggregationInterface $aggregations + * @return $this + */ + public function setAggregations($aggregations) + { + $this->aggregations = $aggregations; + return $this; + } + + /** + * Get search criteria. + * + * @return \Magento\Framework\Api\SearchCriteriaInterface|null + */ + public function getSearchCriteria() + { + return null; + } + + /** + * Set search criteria. + * + * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria + * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function setSearchCriteria(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria = null) + { + return $this; + } + + /** + * Get total count. + * + * @return int + */ + public function getTotalCount() + { + return $this->getSize(); + } + + /** + * Set total count. + * + * @param int $totalCount + * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function setTotalCount($totalCount) + { + return $this; + } + + /** + * Set items list. + * + * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items + * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function setItems(array $items = null) + { return $this; } } diff --git a/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php b/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php new file mode 100644 index 0000000000000..173b3c8f68b55 --- /dev/null +++ b/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php @@ -0,0 +1,128 @@ +entityFactoryMock = $this->getMockBuilder(EntityFactoryInterface::class) + ->getMockForAbstractClass(); + $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) + ->getMockForAbstractClass(); + $this->fetchStrategyMock = $this->getMockBuilder(FetchStrategyInterface::class) + ->getMockForAbstractClass(); + $this->eventManagerMock = $this->getMockBuilder(ManagerInterface::class) + ->getMockForAbstractClass(); + $this->resourceMock = $this->getMockBuilder(AbstractDb::class) + ->disableOriginalConstructor() + ->getMock(); + $this->aggregationsMock = $this->getMockBuilder(AggregationInterface::class) + ->getMockForAbstractClass(); + $this->connectionMock = $this->getMockBuilder(AdapterInterface::class) + ->getMockForAbstractClass(); + $this->selectMock = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->resourceMock->expects($this->any()) + ->method('getConnection') + ->willReturn($this->connectionMock); + $this->connectionMock->expects($this->once()) + ->method('select') + ->willReturn($this->selectMock); + + $this->model = (new ObjectManager($this))->getObject(Collection::class, [ + 'entityFactory' => $this->entityFactoryMock, + 'logger' => $this->loggerMock, + 'fetchStrategy' => $this->fetchStrategyMock, + 'eventManager' => $this->eventManagerMock, + 'mainTable' => null, + 'eventPrefix' => 'test_event_prefix', + 'eventObject' => 'test_event_object', + 'resourceModel' => null, + 'resource' => $this->resourceMock, + ]); + } + + /** + * @covers \Magento\Theme\Model\ResourceModel\Theme\Grid\Collection::setSearchCriteria + * @covers \Magento\Theme\Model\ResourceModel\Theme\Grid\Collection::getAggregations + */ + public function testSetGetAggregations() + { + $this->model->setAggregations($this->aggregationsMock); + $this->assertInstanceOf(AggregationInterface::class, $this->model->getAggregations()); + } + + /** + * @covers \Magento\Theme\Model\ResourceModel\Theme\Grid\Collection::setSearchCriteria + */ + public function testSetSearchCriteria() + { + $this->assertEquals($this->model, $this->model->setSearchCriteria()); + } +} diff --git a/app/code/Magento/Theme/etc/di.xml b/app/code/Magento/Theme/etc/di.xml index c20184fec6bc4..cfe1b05deb188 100644 --- a/app/code/Magento/Theme/etc/di.xml +++ b/app/code/Magento/Theme/etc/di.xml @@ -108,6 +108,7 @@ Magento\Theme\Model\ResourceModel\Design\Config\Grid\Collection + Magento\Theme\Model\ResourceModel\Theme\Grid\Collection @@ -273,4 +274,12 @@ Magento\Theme\Model\ResourceModel\Theme\Collection + + + theme + theme_grid_collection + theme_collection + Magento\Theme\Model\ResourceModel\Theme\Collection + + diff --git a/app/code/Magento/Theme/i18n/en_US.csv b/app/code/Magento/Theme/i18n/en_US.csv index 2b8765c36d24a..14cc472a50d9e 100644 --- a/app/code/Magento/Theme/i18n/en_US.csv +++ b/app/code/Magento/Theme/i18n/en_US.csv @@ -185,3 +185,4 @@ Settings,Settings "2 columns with left bar","2 columns with left bar" "2 columns with right bar","2 columns with right bar" "3 columns","3 columns" +ID,ID diff --git a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_index.xml b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_index.xml index 7bbdc526a6143..3b377899b9199 100644 --- a/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_index.xml +++ b/app/code/Magento/Theme/view/adminhtml/layout/adminhtml_system_design_theme_index.xml @@ -6,11 +6,9 @@ */ --> - - - + diff --git a/app/code/Magento/Theme/view/adminhtml/ui_component/design_theme_listing.xml b/app/code/Magento/Theme/view/adminhtml/ui_component/design_theme_listing.xml new file mode 100644 index 0000000000000..4bbb5656ae3ca --- /dev/null +++ b/app/code/Magento/Theme/view/adminhtml/ui_component/design_theme_listing.xml @@ -0,0 +1,66 @@ + + ++ + + design_theme_listing.design_theme_listing_data_source + + + + design_theme_columns + + design_theme_listing.design_theme_listing_data_source + + + + + + + Magento_Theme::theme + + + id + theme_id + + + + + + + + + + + + + textRange + + asc + false + + + + + text + + + + + + text + + + + + + text + + + + + From 4033593b66c31ed94319c478b35ee6fdef10d581 Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 31 Mar 2018 08:48:36 +0300 Subject: [PATCH 0053/2023] Updated test for theme index controller --- .../Adminhtml/System/Design/Theme/IndexTest.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Adminhtml/System/Design/Theme/IndexTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Adminhtml/System/Design/Theme/IndexTest.php index a5acb67f93974..213d8dde8689f 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Adminhtml/System/Design/Theme/IndexTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Adminhtml/System/Design/Theme/IndexTest.php @@ -28,13 +28,18 @@ public function testIndexAction() ->method('getMenuModel') ->will($this->returnValue($menuModel)); + $titleBlock = $this->createMock(\Magento\Theme\Block\Html\Title::class); + $titleBlock->expects($this->once())->method('setPageTitle'); + $layout = $this->createMock(\Magento\Framework\View\LayoutInterface::class); $layout->expects($this->any()) ->method('getBlock') - ->with($this->equalTo('menu')) - ->will($this->returnValue($menuBlock)); + ->willReturnMap([ + ['menu', $menuBlock], + ['page.title', $titleBlock] + ]); - $this->view->expects($this->once()) + $this->view->expects($this->any()) ->method('getLayout') ->will($this->returnValue($layout)); From 7f04c715b0d53b2a95b441c72209fb3daf9e0635 Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 31 Mar 2018 08:57:58 +0300 Subject: [PATCH 0054/2023] Updated AggregationInterface location --- .../Theme/Model/ResourceModel/Theme/Grid/Collection.php | 2 +- .../Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/Model/ResourceModel/Theme/Grid/Collection.php b/app/code/Magento/Theme/Model/ResourceModel/Theme/Grid/Collection.php index 841f4fb8c3e63..64a18b42ab240 100644 --- a/app/code/Magento/Theme/Model/ResourceModel/Theme/Grid/Collection.php +++ b/app/code/Magento/Theme/Model/ResourceModel/Theme/Grid/Collection.php @@ -7,7 +7,7 @@ use Magento\Theme\Model\ResourceModel\Theme\Collection as ThemeCollection; use Magento\Framework\Api\Search\SearchResultInterface; -use Magento\Framework\Search\AggregationInterface; +use Magento\Framework\Api\Search\AggregationInterface; /** * Theme grid collection diff --git a/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php b/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php index 173b3c8f68b55..fcaba91c39abd 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php @@ -67,6 +67,11 @@ class CollectionTest extends \PHPUnit\Framework\TestCase */ protected $model; + /** + * SetUp method + * + * @return void + */ protected function setUp() { $this->entityFactoryMock = $this->getMockBuilder(EntityFactoryInterface::class) From 82563693c2428d4fcbc3df3e66e11652cbbc90aa Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 31 Mar 2018 10:10:41 +0300 Subject: [PATCH 0055/2023] Added strict type declaration for collection test --- .../Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php b/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php index fcaba91c39abd..900dbf75ef5bb 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/ResourceModel/Theme/Grid/CollectionTest.php @@ -3,6 +3,9 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +declare(strict_types=1); + namespace Magento\Theme\Test\Unit\Model\ResourceModel\Theme\Grid; use Magento\Theme\Model\ResourceModel\Theme\Grid\Collection; From 8f3a4ed5f657cce3caa181a40b14f3d3f94e8221 Mon Sep 17 00:00:00 2001 From: Stas Kozar Date: Wed, 4 Apr 2018 10:58:56 +0300 Subject: [PATCH 0056/2023] MAGETWO-72775: is_subscribed extended attribute isn't returned in REST customer calls --- .../Model/Plugin/CustomerPlugin.php | 104 +++++++- .../Unit/Model/Plugin/CustomerPluginTest.php | 223 +++++++++++++----- .../Customer/Model/CustomerMetadataTest.php | 6 + 3 files changed, 267 insertions(+), 66 deletions(-) diff --git a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php index b82d6fe06918f..ce46c856ffa0d 100644 --- a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php +++ b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php @@ -8,6 +8,9 @@ use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository; use Magento\Customer\Api\Data\CustomerInterface; use Magento\Newsletter\Model\SubscriberFactory; +use Magento\Framework\Api\ExtensionAttributesFactory; +use Magento\Newsletter\Model\ResourceModel\Subscriber; +use Magento\Customer\Api\Data\CustomerExtensionInterface; class CustomerPlugin { @@ -18,14 +21,36 @@ class CustomerPlugin */ private $subscriberFactory; + /** + * @var ExtensionAttributesFactory + */ + private $extensionFactory; + + /** + * @var Subscriber + */ + private $subscriberResource; + + /** + * @var array + */ + private $customerSubscriptionStatus = []; + /** * Initialize dependencies. * * @param SubscriberFactory $subscriberFactory + * @param ExtensionAttributesFactory|null $extensionFactory + * @param Subscriber|null $subscriberResource */ - public function __construct(SubscriberFactory $subscriberFactory) - { + public function __construct( + SubscriberFactory $subscriberFactory, + ExtensionAttributesFactory $extensionFactory, + Subscriber $subscriberResource + ) { $this->subscriberFactory = $subscriberFactory; + $this->extensionFactory = $extensionFactory; + $this->subscriberResource = $subscriberResource; } /** @@ -41,14 +66,34 @@ public function __construct(SubscriberFactory $subscriberFactory) */ public function afterSave(CustomerRepository $subject, CustomerInterface $result, CustomerInterface $customer) { - $this->subscriberFactory->create()->updateSubscription($result->getId()); - if ($result->getId() && $customer->getExtensionAttributes()) { - if ($customer->getExtensionAttributes()->getIsSubscribed() === true) { - $this->subscriberFactory->create()->subscribeCustomerById($result->getId()); - } elseif ($customer->getExtensionAttributes()->getIsSubscribed() === false) { - $this->subscriberFactory->create()->unsubscribeCustomerById($result->getId()); + $resultId = $result->getId(); + /** @var \Magento\Newsletter\Model\Subscriber $subscriber */ + $subscriber = $this->subscriberFactory->create(); + + $subscriber->updateSubscription($resultId); + // update the result only if the original customer instance had different value. + $initialExtensionAttributes = $result->getExtensionAttributes(); + if ($initialExtensionAttributes === null) { + /** @var CustomerExtensionInterface $initialExtensionAttributes */ + $initialExtensionAttributes = $this->extensionFactory->create(CustomerInterface::class); + $result->setExtensionAttributes($initialExtensionAttributes); + } + + $newExtensionAttributes = $customer->getExtensionAttributes(); + if ($newExtensionAttributes + && $initialExtensionAttributes->getIsSubscribed() !== $newExtensionAttributes->getIsSubscribed() + ) { + if ($newExtensionAttributes->getIsSubscribed() === true) { + $subscriber->subscribeCustomerById($resultId); + } elseif ($newExtensionAttributes->getIsSubscribed() === false) { + $subscriber->unsubscribeCustomerById($resultId); } } + + $isSubscribed = $subscriber->isSubscribed(); + $this->customerSubscriptionStatus[$resultId] = $isSubscribed; + $initialExtensionAttributes->setIsSubscribed($isSubscribed); + return $result; } @@ -94,4 +139,47 @@ public function afterDelete(CustomerRepository $subject, $result, CustomerInterf } return $result; } + + /** + * Plugin after getById customer that obtains newsletter subscription status for given customer. + * + * @param CustomerRepository $subject + * @param CustomerInterface $customer + * @return CustomerInterface + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetById(CustomerRepository $subject, CustomerInterface $customer) + { + $extensionAttributes = $customer->getExtensionAttributes(); + + if ($extensionAttributes === null) { + /** @var CustomerExtensionInterface $extensionAttributes */ + $extensionAttributes = $this->extensionFactory->create(CustomerInterface::class); + $customer->setExtensionAttributes($extensionAttributes); + } + if ($extensionAttributes->getIsSubscribed() === null) { + $isSubscribed = $this->isSubscribed($customer); + $extensionAttributes->setIsSubscribed($isSubscribed); + } + + return $customer; + } + + /** + * This method returns newsletters subscription status for given customer. + * + * @param CustomerInterface $customer + * @return bool + */ + private function isSubscribed(CustomerInterface $customer) + { + $customerId = $customer->getId(); + if (!isset($this->customerSubscriptionStatus[$customerId])) { + $subscriber = $this->subscriberResource->loadByCustomerData($customer); + $this->customerSubscriptionStatus[$customerId] = isset($subscriber['subscriber_status']) + && $subscriber['subscriber_status'] == 1; + } + + return $this->customerSubscriptionStatus[$customerId]; + } } diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php index 47d4584857bde..f4f9663904aa0 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php @@ -7,13 +7,16 @@ use Magento\Customer\Api\Data\CustomerInterface; use Magento\Customer\Model\ResourceModel\CustomerRepository; +use Magento\Customer\Api\Data\CustomerExtensionInterface; +use Magento\Framework\Api\ExtensionAttributesFactory; +use Magento\Newsletter\Model\ResourceModel\Subscriber; class CustomerPluginTest extends \PHPUnit\Framework\TestCase { /** * @var \Magento\Newsletter\Model\Plugin\CustomerPlugin */ - protected $plugin; + private $plugin; /** * @var \Magento\Newsletter\Model\SubscriberFactory|\PHPUnit_Framework_MockObject_MockObject @@ -28,7 +31,27 @@ class CustomerPluginTest extends \PHPUnit\Framework\TestCase /** * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ - protected $objectManager; + private $objectManager; + + /** + * @var ExtensionAttributesFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $extensionFactoryMock; + + /** + * @var CustomerExtensionInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $customerExtensionMock; + + /** + * @var Subscriber|\PHPUnit_Framework_MockObject_MockObject + */ + private $subscriberResourceMock; + + /** + * @var CustomerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $customerMock; protected function setUp() { @@ -44,92 +67,101 @@ protected function setUp() 'delete', 'updateSubscription', 'subscribeCustomerById', - 'unsubscribeCustomerById' + 'unsubscribeCustomerById', + 'isSubscribed' ] )->disableOriginalConstructor() ->getMock(); + $this->extensionFactoryMock = $this->getMockBuilder(ExtensionAttributesFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->customerExtensionMock = $this->getMockBuilder(CustomerExtensionInterface::class) + ->setMethods(["getIsSubscribed", "setIsSubscribed"]) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->subscriberResourceMock = $this->getMockBuilder(Subscriber::class) + ->disableOriginalConstructor() + ->getMock(); + $this->customerMock = $this->getMockBuilder(CustomerInterface::class) + ->setMethods(["getExtensionAttributes"]) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $this->subscriberFactory->expects($this->any())->method('create')->willReturn($this->subscriber); - $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->plugin = $this->objectManager->getObject( \Magento\Newsletter\Model\Plugin\CustomerPlugin::class, [ - 'subscriberFactory' => $this->subscriberFactory + 'subscriberFactory' => $this->subscriberFactory, + 'extensionFactory' => $this->extensionFactoryMock, + 'subscriberResource' => $this->subscriberResourceMock, ] ); } - public function testAfterSaveWithoutIsSubscribed() + /** + * @param bool $subscriptionOriginalValue + * @param bool $subscriptionNewValue + * @dataProvider afterSaveDataProvider + */ + public function testAfterSave($subscriptionOriginalValue, $subscriptionNewValue) { $customerId = 1; - /** @var CustomerInterface | \PHPUnit_Framework_MockObject_MockObject $customer */ - $customer = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class); + /** @var CustomerInterface | \PHPUnit_Framework_MockObject_MockObject $result */ + $result = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class); /** @var CustomerRepository | \PHPUnit_Framework_MockObject_MockObject $subject */ $subject = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); - $customer->expects($this->atLeastOnce()) - ->method("getId") - ->willReturn($customerId); + /** @var CustomerExtensionInterface|\PHPUnit_Framework_MockObject_MockObject $resultExtensionAttributes */ + $resultExtensionAttributes = $this->getMockBuilder(CustomerExtensionInterface::class) + ->setMethods(['getIsSubscribed', 'setIsSubscribed']) + ->getMockForAbstractClass(); + $result->expects($this->atLeastOnce())->method('getId')->willReturn($customerId); + $result->expects($this->any())->method('getExtensionAttributes')->willReturn(null); + $this->extensionFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($resultExtensionAttributes); + $result->expects($this->once()) + ->method('setExtensionAttributes') + ->with($resultExtensionAttributes) + ->willReturnSelf(); + $this->customerMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($this->customerExtensionMock); + $resultExtensionAttributes->expects($this->any()) + ->method('getIsSubscribed') + ->willReturn($subscriptionOriginalValue); + $this->customerExtensionMock->expects($this->any()) + ->method('getIsSubscribed') + ->willReturn($subscriptionNewValue); + + if ($subscriptionOriginalValue !== $subscriptionNewValue) { + if ($subscriptionNewValue === true) { + $this->subscriber->expects($this->once())->method('subscribeCustomerById')->with($customerId); + } elseif ($subscriptionNewValue === false) { + $this->subscriber->expects($this->once())->method('unsubscribeCustomerById')->with($customerId); + } + $this->subscriber->expects($this->once())->method('isSubscribed')->willReturn($subscriptionNewValue); + $resultExtensionAttributes->expects($this->once())->method('setIsSubscribed')->with($subscriptionNewValue); + } - $this->assertEquals($customer, $this->plugin->afterSave($subject, $customer, $customer)); + $this->assertEquals($result, $this->plugin->afterSave($subject, $result, $this->customerMock)); } /** * @return array */ - public function afterSaveExtensionAttributeDataProvider() + public function afterSaveDataProvider() { return [ [true, true], - [false, false] + [false, false], + [true, false], + [false, true], ]; } - /** - * @param boolean $isSubscribed - * @param boolean $subscribeIsCreated - * @dataProvider afterSaveExtensionAttributeDataProvider - */ - public function testAfterSaveWithIsSubscribed($isSubscribed, $subscribeIsCreated) - { - $customerId = 1; - /** @var CustomerInterface | \PHPUnit_Framework_MockObject_MockObject $customer */ - $customer = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class); - $extensionAttributes = $this - ->getMockBuilder(\Magento\Customer\Api\Data\CustomerExtensionInterface::class) - ->setMethods(["getIsSubscribed", "setIsSubscribed"]) - ->getMockForAbstractClass(); - - $extensionAttributes - ->expects($this->atLeastOnce()) - ->method("getIsSubscribed") - ->willReturn($isSubscribed); - - $customer->expects($this->atLeastOnce()) - ->method("getExtensionAttributes") - ->willReturn($extensionAttributes); - - if ($subscribeIsCreated) { - $this->subscriber->expects($this->once()) - ->method("subscribeCustomerById") - ->with($customerId); - } else { - $this->subscriber->expects($this->once()) - ->method("unsubscribeCustomerById") - ->with($customerId); - } - - /** @var CustomerRepository | \PHPUnit_Framework_MockObject_MockObject $subject */ - $subject = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); - - $customer->expects($this->atLeastOnce()) - ->method("getId") - ->willReturn($customerId); - - $this->assertEquals($customer, $this->plugin->afterSave($subject, $customer, $customer)); - } - public function testAfterDelete() { $subject = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); @@ -158,4 +190,79 @@ public function testAroundDeleteById() $this->assertEquals(true, $this->plugin->aroundDeleteById($subject, $deleteCustomerById, $customerId)); } + + /** + * @param int|null $subscriberStatusKey + * @param int|null $subscriberStatusValue + * @param bool $isSubscribed + * @dataProvider afterGetByIdDataProvider + */ + public function testAfterGetByIdCreatesExtensionAttributesIfItIsNotSet( + $subscriberStatusKey, + $subscriberStatusValue, + $isSubscribed + ) { + $subject = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); + $subscriber = [$subscriberStatusKey => $subscriberStatusValue]; + + $this->extensionFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->customerExtensionMock); + $this->customerMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($this->customerExtensionMock) + ->willReturnSelf(); + $this->customerMock->expects($this->any()) + ->method('getId') + ->willReturn(1); + $this->subscriberResourceMock->expects($this->once()) + ->method('loadByCustomerData') + ->with($this->customerMock) + ->willReturn($subscriber); + $this->customerExtensionMock->expects($this->once())->method('setIsSubscribed')->with($isSubscribed); + + $this->assertEquals( + $this->customerMock, + $this->plugin->afterGetById($subject, $this->customerMock) + ); + } + + public function testAfterGetByIdSetsIsSubscribedFlagIfItIsNotSet() + { + $subject = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); + $subscriber = ['subscriber_id' => 1, 'subscriber_status' => 1]; + + $this->customerMock->expects($this->any()) + ->method('getExtensionAttributes') + ->willReturn($this->customerExtensionMock); + $this->customerExtensionMock->expects($this->any()) + ->method('getIsSubscribed') + ->willReturn(null); + $this->subscriberResourceMock->expects($this->once()) + ->method('loadByCustomerData') + ->with($this->customerMock) + ->willReturn($subscriber); + $this->customerExtensionMock->expects($this->once()) + ->method('setIsSubscribed') + ->willReturnSelf(); + + $this->assertEquals( + $this->customerMock, + $this->plugin->afterGetById($subject, $this->customerMock) + ); + } + + /** + * @return array + */ + public function afterGetByIdDataProvider() + { + return [ + ['subscriber_status', 1, true], + ['subscriber_status', 2, false], + ['subscriber_status', 3, false], + ['subscriber_status', 4, false], + [null, null, false], + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php index eb62eb886fd5d..3ed330ed98d6b 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php @@ -231,6 +231,12 @@ public function testGetCustomerAttributeMetadata() ); $this->assertNotEmpty($attributes); + // remove odd extension attributes + $allAtrributes = $expectAttrsWithVals; + $allAtrributes['created_at'] = $attributes['created_at']; + $allAtrributes['updated_at'] = $attributes['updated_at']; + $attributes = array_intersect_key($attributes, $allAtrributes); + foreach ($attributes as $attributeCode => $attributeValue) { $this->assertNotNull($attributeCode); $this->assertNotNull($attributeValue); From 8db32a794f777166548b20767e2ef435219fbd90 Mon Sep 17 00:00:00 2001 From: Viktor Sevch Date: Wed, 4 Apr 2018 18:20:35 +0300 Subject: [PATCH 0057/2023] MAGETWO-83820: [2.3.x] SKU parameter in capital letters on CSV ignored by database in Import but OK'd by validator --- .../Import/Product/Type/Configurable.php | 44 ++++++++++++++++--- .../Import/Product/Type/ConfigurableTest.php | 41 +++++++++++++++++ 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php index 3dc47b42c1e40..cd71ffdc72ed1 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php @@ -11,6 +11,7 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\CatalogImportExport\Model\Import\Product as ImportProduct; use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\Exception\LocalizedException; /** * Importing configurable products @@ -32,16 +33,24 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ const ERROR_DUPLICATED_VARIATIONS = 'duplicatedVariations'; + const ERROR_UNIDENTIFIABLE_VARIATION = 'unidentifiableVariation'; + /** * Validation failure message template definitions * * @var array */ protected $_messageTemplates = [ - self::ERROR_ATTRIBUTE_CODE_IS_NOT_SUPER => 'Attribute with code "%s" is not super', - self::ERROR_INVALID_OPTION_VALUE => 'Invalid option value for attribute "%s"', - self::ERROR_INVALID_WEBSITE => 'Invalid website code for super attribute', - self::ERROR_DUPLICATED_VARIATIONS => 'SKU %s contains duplicated variations', + self::ERROR_ATTRIBUTE_CODE_IS_NOT_SUPER => + 'Attribute with code "%s" is not super', + self::ERROR_INVALID_OPTION_VALUE => + 'Invalid option value for attribute "%s"', + self::ERROR_INVALID_WEBSITE => + 'Invalid website code for super attribute', + self::ERROR_DUPLICATED_VARIATIONS => + 'SKU %s contains duplicated variations', + self::ERROR_UNIDENTIFIABLE_VARIATION => + 'Configurable variation "%s" is unidentifiable', ]; /** @@ -470,13 +479,14 @@ protected function _processSuperData() * @param array $rowData * * @return array + * @throws LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _parseVariations($rowData) { $additionalRows = []; - if (!isset($rowData['configurable_variations'])) { + if (empty($rowData['configurable_variations'])) { return $additionalRows; } $variations = explode(ImportProduct::PSEUDO_MULTI_LINE_SEPARATOR, $rowData['configurable_variations']); @@ -489,7 +499,8 @@ protected function _parseVariations($rowData) $nameAndValue = explode(ImportProduct::PAIR_NAME_VALUE_SEPARATOR, $nameAndValue); if (!empty($nameAndValue)) { $value = isset($nameAndValue[1]) ? trim($nameAndValue[1]) : ''; - $fieldName = trim($nameAndValue[0]); + // Ignoring field names' case. + $fieldName = strtolower(trim($nameAndValue[0])); if ($fieldName) { $fieldAndValuePairs[$fieldName] = $value; } @@ -510,8 +521,19 @@ protected function _parseVariations($rowData) $additionalRow = []; $position += 1; } + } else { + $errorCode = self::ERROR_UNIDENTIFIABLE_VARIATION; + throw new LocalizedException( + __( + sprintf( + $this->_messageTemplates[$errorCode], + $variation + ) + ) + ); } } + return $additionalRows; } @@ -822,7 +844,14 @@ protected function configurableInBunch($bunch) public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) { $error = false; - $dataWithExtraVirtualRows = $this->_parseVariations($rowData); + try { + $dataWithExtraVirtualRows = $this->_parseVariations($rowData); + } catch (LocalizedException $exception) { + $this->_entityModel->addRowError($exception->getMessage(), $rowNum); + + return false; + } + $skus = []; $rowData['price'] = isset($rowData['price']) && $rowData['price'] ? $rowData['price'] : '0.00'; if (!empty($dataWithExtraVirtualRows)) { @@ -846,6 +875,7 @@ public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) } $error |= !parent::isRowValid($option, $rowNum, $isNewProduct); } + return !$error; } diff --git a/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php b/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php index f6912fe8b6d6c..8cdb5531a3cab 100644 --- a/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php +++ b/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php @@ -560,15 +560,56 @@ public function testIsRowValid() '_type' => 'configurable', '_product_websites' => 'website_1', ]; + // Checking that variations' field names are case-insensitive with this + // product. + $caseInsensitiveSKU = 'configurableskuI22CaseInsensitive'; + $caseInsensitiveProduct = [ + 'sku' => $caseInsensitiveSKU, + 'store_view_code' => null, + 'attribute_set_code' => 'Default', + 'product_type' => 'configurable', + 'name' => 'Configurable Product 21', + 'product_websites' => 'website_1', + 'configurable_variation_labels' => 'testattr2=Select Color, testattr3=Select Size', + 'configurable_variations' => 'SKU=testconf2-attr2val1-testattr3v1,' + . 'testattr2=attr2val1,' + . 'testattr3=testattr3v1,' + . 'display=1|sku=testconf2-attr2val1-testattr3v2,' + . 'testattr2=attr2val1,' + . 'testattr3=testattr3v2,' + . 'display=0', + '_store' => null, + '_attribute_set' => 'Default', + '_type' => 'configurable', + '_product_websites' => 'website_1', + ]; $bunch[] = $badProduct; + $bunch[] = $caseInsensitiveProduct; // Set _attributes to avoid error in Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType. $this->setPropertyValue($this->configurable, '_attributes', [ $badProduct[\Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET] => [], ]); + // Avoiding errors about attributes not being super + $this->setPropertyValue( + $this->configurable, + '_superAttributes', + [ + 'testattr2' => ['options' => ['attr2val1' => 1]], + 'testattr3' => [ + 'options' => [ + 'testattr3v2' => 1, + 'testattr3v1' => 1, + ], + ], + ] + ); foreach ($bunch as $rowData) { $result = $this->configurable->isRowValid($rowData, 0, !isset($this->_oldSku[$rowData['sku']])); $this->assertNotNull($result); + if ($rowData['sku'] === $caseInsensitiveSKU) { + $this->assertTrue($result); + } } } From 45ae775f9e5ee35b015e06266a0772a244d60d2f Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Wed, 4 Apr 2018 16:05:00 -0500 Subject: [PATCH 0058/2023] MAGETWO-87180: Impossible to add product to compare list - Unskipping MFTF test. --- ...minAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml index 0531320cddee2..074a0509be660 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml @@ -17,7 +17,6 @@ - From 812fd84314983cdd87bd2a7347fb24105cd26cd0 Mon Sep 17 00:00:00 2001 From: Freek Vandeursen Date: Thu, 5 Apr 2018 08:42:02 +0200 Subject: [PATCH 0059/2023] Don't forget to unset the port of course --- lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php index e3dd5d5d6b57a..ed27e3d6f6f33 100644 --- a/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php +++ b/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php @@ -555,6 +555,7 @@ protected function _query($sql, $bind = []) */ if (!empty($this->_config['port'])) { $this->_config['host'] = implode(':', [$this->_config['host'], $this->_config['port']]); + unset($this->_config['port']); } $this->_connect(); From 8220e3ff214d8911ba7dde971ed6856272228ca1 Mon Sep 17 00:00:00 2001 From: Vlad Veselov Date: Tue, 27 Mar 2018 11:35:13 +0300 Subject: [PATCH 0060/2023] Remove improper unit test it shall not pass code review as object under test is mocked and thus it does not test anything --- .../Category/Collection/UrlRewriteTest.php | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php deleted file mode 100644 index b1f5f17f64a59..0000000000000 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/Collection/UrlRewriteTest.php +++ /dev/null @@ -1,39 +0,0 @@ -model = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Category\Collection::class) - ->disableOriginalConstructor() - ->setMethodsExcept(['joinUrlRewrite', 'setStoreId', 'getStoreId']) - ->getMock(); - } - - public function testStoreIdUsedByUrlRewrite() - { - $cond = '{{table}}.is_autogenerated = 1 AND {{table}}.store_id = 100 AND {{table}}.entity_type = \'category\''; - $this->model->expects($this->once()) - ->method('joinTable') - ->with( - $this->anything(), - $this->anything(), - $this->anything(), - $this->equalTo($cond), - $this->anything() - ); - $this->model->setStoreId(100); - $this->model->joinUrlRewrite(); - } -} From 2d1bff525144d01b57cca8d2e0fd37f8a045733c Mon Sep 17 00:00:00 2001 From: Stas Kozar Date: Thu, 5 Apr 2018 15:32:20 +0300 Subject: [PATCH 0061/2023] MAGETWO-72775: is_subscribed extended attribute isn't returned in REST customer calls --- .../Newsletter/Model/Plugin/CustomerPlugin.php | 4 ++-- .../Test/Unit/Model/Plugin/CustomerPluginTest.php | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php index ce46c856ffa0d..3a73e1d925323 100644 --- a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php +++ b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php @@ -83,9 +83,9 @@ public function afterSave(CustomerRepository $subject, CustomerInterface $result if ($newExtensionAttributes && $initialExtensionAttributes->getIsSubscribed() !== $newExtensionAttributes->getIsSubscribed() ) { - if ($newExtensionAttributes->getIsSubscribed() === true) { + if ($newExtensionAttributes->getIsSubscribed()) { $subscriber->subscribeCustomerById($resultId); - } elseif ($newExtensionAttributes->getIsSubscribed() === false) { + } else { $subscriber->unsubscribeCustomerById($resultId); } } diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php index f4f9663904aa0..e809b7e37a432 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php @@ -68,7 +68,7 @@ protected function setUp() 'updateSubscription', 'subscribeCustomerById', 'unsubscribeCustomerById', - 'isSubscribed' + 'isSubscribed', ] )->disableOriginalConstructor() ->getMock(); @@ -77,14 +77,14 @@ protected function setUp() ->setMethods(['create']) ->getMock(); $this->customerExtensionMock = $this->getMockBuilder(CustomerExtensionInterface::class) - ->setMethods(["getIsSubscribed", "setIsSubscribed"]) + ->setMethods(['getIsSubscribed', 'setIsSubscribed']) ->disableOriginalConstructor() ->getMockForAbstractClass(); $this->subscriberResourceMock = $this->getMockBuilder(Subscriber::class) ->disableOriginalConstructor() ->getMock(); $this->customerMock = $this->getMockBuilder(CustomerInterface::class) - ->setMethods(["getExtensionAttributes"]) + ->setMethods(['getExtensionAttributes']) ->disableOriginalConstructor() ->getMockForAbstractClass(); $this->subscriberFactory->expects($this->any())->method('create')->willReturn($this->subscriber); @@ -104,6 +104,7 @@ protected function setUp() * @param bool $subscriptionOriginalValue * @param bool $subscriptionNewValue * @dataProvider afterSaveDataProvider + * @return void */ public function testAfterSave($subscriptionOriginalValue, $subscriptionNewValue) { @@ -137,9 +138,9 @@ public function testAfterSave($subscriptionOriginalValue, $subscriptionNewValue) ->willReturn($subscriptionNewValue); if ($subscriptionOriginalValue !== $subscriptionNewValue) { - if ($subscriptionNewValue === true) { + if ($subscriptionNewValue) { $this->subscriber->expects($this->once())->method('subscribeCustomerById')->with($customerId); - } elseif ($subscriptionNewValue === false) { + } else { $this->subscriber->expects($this->once())->method('unsubscribeCustomerById')->with($customerId); } $this->subscriber->expects($this->once())->method('isSubscribed')->willReturn($subscriptionNewValue); @@ -196,6 +197,7 @@ public function testAroundDeleteById() * @param int|null $subscriberStatusValue * @param bool $isSubscribed * @dataProvider afterGetByIdDataProvider + * @return void */ public function testAfterGetByIdCreatesExtensionAttributesIfItIsNotSet( $subscriberStatusKey, From 8a701084cb0e04f98228ba5480b16ab76a8d506c Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Thu, 5 Apr 2018 10:51:54 -0500 Subject: [PATCH 0062/2023] MAGETWO-87180: Impossible to add products - Renamed test file --- ...minAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/{AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml => AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml} (100%) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml similarity index 100% rename from dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeCest.xml rename to dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml From bbf24652007dda9e850b06b2b61f8b3124589e7c Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Thu, 5 Apr 2018 16:39:57 -0500 Subject: [PATCH 0063/2023] MAGETWO-87353: BlockTest::testUpdateTime randomly fails on CI - Changed test implementation to account for race condition with timestamps --- .../testsuite/Magento/Cms/Model/BlockTest.php | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/BlockTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/BlockTest.php index c9544d87bc018..16331ccde245c 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/BlockTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/BlockTest.php @@ -9,6 +9,7 @@ use Magento\Cms\Model\BlockFactory; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Stdlib\DateTime\DateTime; +use Magento\Framework\Stdlib\DateTime\Timezone; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; @@ -81,18 +82,26 @@ public function testGetByIdentifier(array $blockData) */ public function testUpdateTime(array $blockData) { + # Prepare and save the temporary block - $tempBlock = $this->blockFactory->create(); + $beforeTimestamp = $this->objectManager->get(DateTime::class)->timestamp(); + $tempBlock = $this->blockFactory->create(); $tempBlock->setData($blockData); $this->blockResource->save($tempBlock); # Load previously created block and compare identifiers - $storeId = reset($blockData['stores']); - $block = $this->blockIdentifier->execute($blockData['identifier'], $storeId); - $date = $this->objectManager->get(DateTime::class)->date(); - $this->markTestIncomplete('MAGETWO-87353: \Magento\Cms\Model\BlockTest::testUpdateTime randomly fails on CI. ' - . 'Invalid assertion. Application node timestamp may significantly differ from DB node.'); - $this->assertEquals($date, $block->getUpdateTime()); + $storeId = reset($blockData['stores']); + $block = $this->blockIdentifier->execute($blockData['identifier'], $storeId); + $afterTimestamp = $this->objectManager->get(DateTime::class)->timestamp(); + $blockTimestamp = strtotime($block->getUpdateTime()); + + /* + * This test used to fail due to a race condition @see MAGETWO-87353 + * The DB time would be one second older than the check time. The new check allows the DB time + * to be between the test start time and right before the assertion. + */ + $this->assertGreaterThanOrEqual($beforeTimestamp, $blockTimestamp); + $this->assertLessThanOrEqual($afterTimestamp, $blockTimestamp); } /** From f4fc5b9899879e42beb14d891fa79626ced110bd Mon Sep 17 00:00:00 2001 From: "mastuhin.olexnadr" Date: Fri, 6 Apr 2018 12:07:22 +0300 Subject: [PATCH 0064/2023] ENGCOM-1103: [Forwardport] Category\Collection::joinUrlRewrite should use the store set on the collection #14381 --- .../Model/Category/ProductIndexerTest.php | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Category/ProductIndexerTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Category/ProductIndexerTest.php index c877ae1f388f8..5a7c70ebe8064 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Category/ProductIndexerTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Category/ProductIndexerTest.php @@ -208,18 +208,28 @@ public function testCategoryCreate() } /** + * Finds 4 categories + * * @return Category[] */ private function getCategories() { - /** @var Category $category */ - $category = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Catalog\Model\Category::class + $collectionFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory::class ); - $result = $category->getCollection()->addAttributeToSelect('name')->getItems(); - $result = array_slice($result, 2); + /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */ + $collection = $collectionFactory->create(); + + $collection + ->addAttributeToSelect('name') + ->addAttributeToFilter('name', ['in' => [ + 'Category 1', + 'Category 2', + 'Category 3', + 'Category 4', + ]]); - return array_slice($result, 0, 4); + return array_values($collection->getItems()); } } From 663a7d1266728538ab97abd433267a005753f1aa Mon Sep 17 00:00:00 2001 From: DianaRusin Date: Fri, 6 Apr 2018 13:30:32 +0300 Subject: [PATCH 0065/2023] MAGETWO-58213: [GITHUB] Configurable products import doesn't work configurable_variations not imported #5876 --- .../Import/Product/Type/Configurable.php | 20 ++++- .../Import/Product/Type/ConfigurableTest.php | 89 +++++++++++++++++++ ..._configurable_for_multiple_store_views.csv | 5 ++ ...gurable_for_multiple_store_views_error.csv | 4 + 4 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/_files/import_configurable_for_multiple_store_views.csv create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/_files/import_configurable_for_multiple_store_views_error.csv diff --git a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php index 3dc47b42c1e40..a2b89a583df9c 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php @@ -11,6 +11,7 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\CatalogImportExport\Model\Import\Product as ImportProduct; use Magento\Framework\EntityManager\MetadataPool; +use Magento\Framework\Exception\LocalizedException; /** * Importing configurable products @@ -472,12 +473,20 @@ protected function _processSuperData() * @return array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) + * @throws LocalizedException */ protected function _parseVariations($rowData) { $additionalRows = []; - if (!isset($rowData['configurable_variations'])) { + if (empty($rowData['configurable_variations'])) { return $additionalRows; + } elseif(!empty($rowData['store_view_code'])) { + throw new LocalizedException( + __( + 'Product with assigned super attributes should not have specified "%1" value', + 'store_view_code' + ) + ); } $variations = explode(ImportProduct::PSEUDO_MULTI_LINE_SEPARATOR, $rowData['configurable_variations']); foreach ($variations as $variation) { @@ -822,7 +831,14 @@ protected function configurableInBunch($bunch) public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) { $error = false; - $dataWithExtraVirtualRows = $this->_parseVariations($rowData); + try { + $dataWithExtraVirtualRows = $this->_parseVariations($rowData); + } catch (LocalizedException $exception) { + $this->_entityModel->addRowError($exception->getMessage(), $rowNum); + + return false; + } + $skus = []; $rowData['price'] = isset($rowData['price']) && $rowData['price'] ? $rowData['price'] : '0.00'; if (!empty($dataWithExtraVirtualRows)) { diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/Product/Type/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/Product/Type/ConfigurableTest.php index ebd8b78e52e58..c4b94e223ebd0 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/Product/Type/ConfigurableTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/Product/Type/ConfigurableTest.php @@ -10,6 +10,7 @@ /** * @magentoAppArea adminhtml + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ConfigurableTest extends \PHPUnit\Framework\TestCase { @@ -64,6 +65,7 @@ public function configurableImportDataProvider() * @param $optionSkuList Name of variations for configurable product * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php * @magentoAppArea adminhtml + * @magentoAppIsolation enabled * @dataProvider configurableImportDataProvider */ public function testConfigurableImport($pathToFile, $productName, $optionSkuList) @@ -148,4 +150,91 @@ public function testConfigurableImport($pathToFile, $productName, $optionSkuList $this->assertEquals(2, count($valuesData)); } } + + /** + * @magentoDataFixture Magento/Store/_files/second_store.php + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php + * @magentoAppArea adminhtml + * @magentoAppIsolation enabled + */ + public function testConfigurableImportWithMultipleStores() + { + $productSku = 'Configurable 1'; + $products = [ + 'default' => 'Configurable 1', + 'fixture_second_store' => 'Configurable 1 Second Store', + ]; + $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/import_configurable_for_multiple_store_views.csv', + 'directory' => $directory, + ] + ); + $errors = $this->model->setSource( + $source + )->setParameters( + [ + 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, + 'entity' => 'catalog_product', + ] + )->validateData(); + + $this->assertTrue($errors->getErrorsCount() == 0); + $this->model->importData(); + + foreach ($products as $storeCode => $productName) { + $store = $this->objectManager->create(\Magento\Store\Model\Store::class); + $store->load($storeCode, 'code'); + /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); + /** @var \Magento\Catalog\Api\Data\ProductInterface $product */ + $product = $productRepository->get($productSku, 0, $store->getId()); + $this->assertFalse($product->isObjectNew()); + $this->assertEquals($productName, $product->getName()); + $this->assertEquals(self::TEST_PRODUCT_TYPE, $product->getTypeId()); + } + } + + /** + * @magentoDataFixture Magento/Store/_files/second_store.php + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php + * @magentoDbIsolation disabled + * @magentoAppArea adminhtml + */ + public function testConfigurableImportWithStoreSpecifiedMainItem() + { + { + $expectedErrorMessage = 'Product with assigned super attributes should not have specified "store_view_code"' + . ' value'; + $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/import_configurable_for_multiple_store_views_error.csv', + 'directory' => $directory, + ] + ); + $errors = $this->model->setSource( + $source + )->setParameters( + [ + 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, + 'entity' => 'catalog_product', + ] + )->validateData(); + + $this->assertTrue($errors->getErrorsCount() == 1); + $this->assertEquals($expectedErrorMessage, $errors->getAllErrors()[0]->getErrorMessage()); + } + } } diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/_files/import_configurable_for_multiple_store_views.csv b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/_files/import_configurable_for_multiple_store_views.csv new file mode 100644 index 0000000000000..f776f137d87ce --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/_files/import_configurable_for_multiple_store_views.csv @@ -0,0 +1,5 @@ +sku,store_view_code,attribute_set_code,product_type,name,description,short_description,weight,product_online,tax_class_name,visibility,price,url_key,display_product_options_in,map_price,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,configurable_variations,configurable_variation_labels,associated_skus +Configurable 1-Option 1,,Default,simple,Configurable 1-Option 1,,,,1,Taxable Goods,Not Visible Individually,10,configurable-1-option-1,Block after Info Column,,"attribute_with_option=Option Label,has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 1",99999,0,0,0,0,1,1,0,0,0,1,,1,1,0,0,1,0,0,0,1,,, +Configurable 1-Option 2,,Default,simple,Configurable 1-Option 2,,,,1,Taxable Goods,Not Visible Individually,10,configurable-1-option-2,Block after Info Column,,"has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 2",99999,0,0,0,0,1,1,0,0,0,1,,1,1,0,0,1,0,0,0,1,,, +Configurable 1,,Default,configurable,Configurable 1,,,,1,Taxable Goods,"Catalog, Search",10,configurable-1,Block after Info Column,,"has_options=1,quantity_and_stock_status=In Stock,required_options=0",0,0,0,0,0,1,1,0,0,0,1,,1,0,0,0,1,0,0,0,1,"sku=Configurable 1-Option 1,test_configurable=Option 1|sku=Configurable 1-Option 2,test_configurable=Option 2",test_configurable=test_configurable_custom_label, +Configurable 1,fixture_second_store,Default,configurable,Configurable 1 Second Store,,,,1,Taxable Goods,"Catalog, Search",10,configurable-1,Block after Info Column,,"has_options=1,quantity_and_stock_status=In Stock,required_options=0",0,0,0,0,0,1,1,0,0,0,1,,1,0,0,0,1,0,0,0,1,,test_configurable=test_configurable_custom_label_second_store, diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/_files/import_configurable_for_multiple_store_views_error.csv b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/_files/import_configurable_for_multiple_store_views_error.csv new file mode 100644 index 0000000000000..d2ede16a647a7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/_files/import_configurable_for_multiple_store_views_error.csv @@ -0,0 +1,4 @@ +sku,store_view_code,attribute_set_code,product_type,name,description,short_description,weight,product_online,tax_class_name,visibility,price,url_key,display_product_options_in,map_price,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,configurable_variations,configurable_variation_labels,associated_skus +Configurable 1-Option 1,,Default,simple,Configurable 1-Option 1,,,,1,Taxable Goods,Not Visible Individually,10,configurable-1-option-1,Block after Info Column,,"attribute_with_option=Option Label,has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 1",99999,0,0,0,0,1,1,0,0,0,1,,1,1,0,0,1,0,0,0,1,,, +Configurable 1-Option 2,,Default,simple,Configurable 1-Option 2,,,,1,Taxable Goods,Not Visible Individually,10,configurable-1-option-2,Block after Info Column,,"has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 2",99999,0,0,0,0,1,1,0,0,0,1,,1,1,0,0,1,0,0,0,1,,, +Configurable 1,default,Default,configurable,Configurable 1,,,,1,Taxable Goods,"Catalog, Search",10,configurable-1,Block after Info Column,,"has_options=1,quantity_and_stock_status=In Stock,required_options=0",0,0,0,0,0,1,1,0,0,0,1,,1,0,0,0,1,0,0,0,1,"sku=Configurable 1-Option 1,test_configurable=Option 1|sku=Configurable 1-Option 2,test_configurable=Option 2",test_configurable=test_configurable_custom_label, From e509cb5cd260e1e66b5b661f62b554e3ed4ae3e5 Mon Sep 17 00:00:00 2001 From: DianaRusin Date: Fri, 6 Apr 2018 14:55:09 +0300 Subject: [PATCH 0066/2023] MAGETWO-58213: [GITHUB] Configurable products import doesn't work configurable_variations not imported #5876 --- .../Model/Import/Product/Type/Configurable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php index 05c287447bcf7..6b168dcc2b458 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php @@ -479,7 +479,7 @@ protected function _parseVariations($rowData) $additionalRows = []; if (empty($rowData['configurable_variations'])) { return $additionalRows; - } elseif(!empty($rowData['store_view_code'])) { + } elseif (!empty($rowData['store_view_code'])) { throw new LocalizedException( __( 'Product with assigned super attributes should not have specified "%1" value', From 43580cba2f7af2f4ab18636fa94428dd1226c147 Mon Sep 17 00:00:00 2001 From: Stas Kozar Date: Fri, 6 Apr 2018 16:02:28 +0300 Subject: [PATCH 0067/2023] MAGETWO-72775: is_subscribed extended attribute isn't returned in REST customer calls --- app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php index 3a73e1d925323..22b31575debbc 100644 --- a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php +++ b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php @@ -40,8 +40,8 @@ class CustomerPlugin * Initialize dependencies. * * @param SubscriberFactory $subscriberFactory - * @param ExtensionAttributesFactory|null $extensionFactory - * @param Subscriber|null $subscriberResource + * @param ExtensionAttributesFactory $extensionFactory + * @param Subscriber $subscriberResource */ public function __construct( SubscriberFactory $subscriberFactory, From fb654a6182ff9355bd8c06e53fa7a05a8703d90f Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Fri, 6 Apr 2018 12:42:47 -0500 Subject: [PATCH 0068/2023] MAGETWO-86795: Admin Create Customer functional test fails on B2B edition - Updated tests and action groups to correctly support B2B --- .../ActionGroup/SearchAndMultiselectActionGroup.xml | 7 ++++--- .../FunctionalTest/Customer/Data/CustomerGroupData.xml | 6 ++++++ .../Section/AdminNewCustomerAccountInformationSection.xml | 1 + .../Customer/Test/AdminCreateCustomerTest.xml | 1 - 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/SearchAndMultiselectActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/SearchAndMultiselectActionGroup.xml index a0546ec8bca0e..1c3251864127c 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/SearchAndMultiselectActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/SearchAndMultiselectActionGroup.xml @@ -10,13 +10,14 @@ xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> - - + + + - + [{{options}}] diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Data/CustomerGroupData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Data/CustomerGroupData.xml index 61e0c05ea82a6..49290abad1be1 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Data/CustomerGroupData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Data/CustomerGroupData.xml @@ -13,4 +13,10 @@ 3 Retail Customer + + + + General + + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Section/AdminNewCustomerAccountInformationSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Section/AdminNewCustomerAccountInformationSection.xml index 1c1424f0eb23c..371801d2e76aa 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Section/AdminNewCustomerAccountInformationSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Section/AdminNewCustomerAccountInformationSection.xml @@ -12,5 +12,6 @@ +
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Test/AdminCreateCustomerTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Test/AdminCreateCustomerTest.xml index 5efa9c699b2b9..b678528409501 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Test/AdminCreateCustomerTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Customer/Test/AdminCreateCustomerTest.xml @@ -18,7 +18,6 @@ - From cfa160903307359cc3de11e5e781774e289276e5 Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Mon, 9 Apr 2018 12:10:14 -0500 Subject: [PATCH 0069/2023] MAGETWO-89373: Second-to-last folder is selected in media gallery Continue recursively opening if path.length == 1 --- app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js b/app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js index 62b5648f4a278..9f082b2ce32ce 100644 --- a/app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js +++ b/app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js @@ -94,7 +94,7 @@ define([ lastExistentFolderEl = folderEl; - if (path.length > 1) { + if (path.length) { tree.jstree('open_node', folderEl, recursiveOpen); } else { tree.jstree('open_node', folderEl, function () { From 48855decbe8730f43f47ffedb9c6a0938ffdef5c Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Mon, 9 Apr 2018 15:10:27 -0500 Subject: [PATCH 0070/2023] MAGETWO-88232: Images from WYSIWYG (Text, Slider) do not show up on admin preview nor storefront Add directive preview converter to text and banner, and fix directive conversion --- app/code/Magento/Cms/Helper/Wysiwyg/Images.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Cms/Helper/Wysiwyg/Images.php b/app/code/Magento/Cms/Helper/Wysiwyg/Images.php index 4cddc23239b18..a509b6009cad8 100644 --- a/app/code/Magento/Cms/Helper/Wysiwyg/Images.php +++ b/app/code/Magento/Cms/Helper/Wysiwyg/Images.php @@ -213,12 +213,15 @@ public function getImageHtmlDeclaration($filename, $renderAsTag = false) $html = $fileUrl; } else { $directive = $this->urlEncoder->encode($directive); - $html = $this->_backendData->getUrl( - 'cms/wysiwyg/directive', - [ - '___directive' => $directive, - '_escape_params' => false, - ] + $html = rtrim( + $this->_backendData->getUrl( + 'cms/wysiwyg/directive', + [ + '___directive' => $directive, + '_escape_params' => false, + ] + ), + '/' ); } } From 475ae2315638ec11e3a2d6754f080ce0ce3148b5 Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Mon, 9 Apr 2018 15:30:35 -0500 Subject: [PATCH 0071/2023] MAGETWO-90241: Image Uploader maxFileSize configuration can exceed PHP's upload_max_filesize Use the minimum of the two configurations if both are present --- .../Ui/Component/Form/Element/DataType/Media/Image.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Media/Image.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Media/Image.php index 130d5037e77f7..cab96d796c63e 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Media/Image.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Media/Image.php @@ -64,7 +64,10 @@ public function getComponentName() public function prepare() { // dynamically set max file size based on php ini config if not present in XML - $maxFileSize = $this->getConfiguration()['maxFileSize'] ?? $this->fileSize->getMaxFileSize(); + $maxFileSize = min(array_filter([ + $this->getConfiguration()['maxFileSize'] ?? null, + $this->fileSize->getMaxFileSize() + ])); $data = array_replace_recursive( $this->getData(), From b9732d7d1055c03fb353254b32a30b154234be67 Mon Sep 17 00:00:00 2001 From: Eric COURTIAL Date: Mon, 9 Apr 2018 19:46:39 -0400 Subject: [PATCH 0072/2023] Added possibility to select PHP input file mode --- lib/internal/Magento/Framework/File/Csv.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/File/Csv.php b/lib/internal/Magento/Framework/File/Csv.php index 3d177f89e2968..67177445a670d 100644 --- a/lib/internal/Magento/Framework/File/Csv.php +++ b/lib/internal/Magento/Framework/File/Csv.php @@ -126,13 +126,17 @@ public function getDataPairs($file, $keyIndex = 0, $valueIndex = 1) /** * Saving data row array into file * - * @param string $file - * @param array $data - * @return $this + * @param string $file + * @param array $data + * @param string $mode + * + * @return $this + * + * @throws \Magento\Framework\Exception\FileSystemException */ - public function saveData($file, $data) + public function saveData($file, $data, $mode = 'w') { - $fh = fopen($file, 'w'); + $fh = fopen($file, $mode); foreach ($data as $dataRow) { $this->file->filePutCsv($fh, $dataRow, $this->_delimiter, $this->_enclosure); } From 8632bc5687a87981540729022726bcde65123087 Mon Sep 17 00:00:00 2001 From: Viktor Sevch Date: Tue, 10 Apr 2018 11:41:46 +0300 Subject: [PATCH 0073/2023] MAGETWO-83820: [2.3.x] SKU parameter in capital letters on CSV ignored by database in Import but OK'd by validator --- .../Model/Import/Product/Type/Configurable.php | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php index b2f98cd51239d..fd15754810790 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php @@ -41,16 +41,11 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ * @var array */ protected $_messageTemplates = [ - self::ERROR_ATTRIBUTE_CODE_IS_NOT_SUPER => - 'Attribute with code "%s" is not super', - self::ERROR_INVALID_OPTION_VALUE => - 'Invalid option value for attribute "%s"', - self::ERROR_INVALID_WEBSITE => - 'Invalid website code for super attribute', - self::ERROR_DUPLICATED_VARIATIONS => - 'SKU %s contains duplicated variations', - self::ERROR_UNIDENTIFIABLE_VARIATION => - 'Configurable variation "%s" is unidentifiable', + self::ERROR_ATTRIBUTE_CODE_IS_NOT_SUPER => 'Attribute with code "%s" is not super', + self::ERROR_INVALID_OPTION_VALUE => 'Invalid option value for attribute "%s"', + self::ERROR_INVALID_WEBSITE => 'Invalid website code for super attribute', + self::ERROR_DUPLICATED_VARIATIONS => 'SKU %s contains duplicated variations', + self::ERROR_UNIDENTIFIABLE_VARIATION => 'Configurable variation "%s" is unidentifiable', ]; /** @@ -521,11 +516,10 @@ protected function _parseVariations($rowData) $position += 1; } } else { - $errorCode = self::ERROR_UNIDENTIFIABLE_VARIATION; throw new LocalizedException( __( sprintf( - $this->_messageTemplates[$errorCode], + $this->_messageTemplates[self::ERROR_UNIDENTIFIABLE_VARIATION], $variation ) ) From c23cbb694e3d6510d6804e1c9ede36267d9aa1a0 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun Date: Tue, 10 Apr 2018 15:59:43 +0300 Subject: [PATCH 0074/2023] MAGETWO-90135: Customer shopping cart not accessible in admin order --- .../Magento/Sales/Model/AdminOrder/Create.php | 3 +- .../Test/Unit/Model/AdminOrder/CreateTest.php | 50 ++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php index 679693abd5540..f34f8a681085d 100644 --- a/app/code/Magento/Sales/Model/AdminOrder/Create.php +++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php @@ -714,9 +714,10 @@ public function getCustomerCart() $this->_cart = $this->quoteFactory->create(); $customerId = (int)$this->getSession()->getCustomerId(); + $storeId = (int)$this->getSession()->getStoreId(); if ($customerId) { try { - $this->_cart = $this->quoteRepository->getForCustomer($customerId); + $this->_cart = $this->quoteRepository->getForCustomer($customerId, [$storeId]); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { $this->_cart->setStore($this->getSession()->getStore()); $customerData = $this->customerRepository->getById($customerId); diff --git a/app/code/Magento/Sales/Test/Unit/Model/AdminOrder/CreateTest.php b/app/code/Magento/Sales/Test/Unit/Model/AdminOrder/CreateTest.php index 3dab9178739b8..91da34c2b8b26 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/AdminOrder/CreateTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/AdminOrder/CreateTest.php @@ -18,12 +18,14 @@ use Magento\Framework\Api\DataObjectHelper; use Magento\Framework\App\RequestInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Model\Quote; use Magento\Quote\Model\Quote\Address; use Magento\Quote\Model\Quote\Item; use Magento\Quote\Model\Quote\Item\Updater; use Magento\Sales\Model\AdminOrder\Create; use Magento\Sales\Model\AdminOrder\Product; +use Magento\Quote\Model\QuoteFactory; use PHPUnit_Framework_MockObject_MockObject as MockObject; /** @@ -39,6 +41,16 @@ class CreateTest extends \PHPUnit\Framework\TestCase */ private $adminOrderCreate; + /** + * @var CartRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $quoteRepository; + + /** + * @var QuoteFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $quoteFactory; + /** * @var SessionQuote|MockObject */ @@ -76,12 +88,22 @@ class CreateTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->sessionQuote = $this->createMock(SessionQuote::class); $this->formFactory = $this->createPartialMock(FormFactory::class, ['create']); + $this->quoteFactory = $this->createPartialMock(QuoteFactory::class, ['create']); $this->customerFactory = $this->createPartialMock(CustomerInterfaceFactory::class, ['create']); $this->itemUpdater = $this->createMock(Updater::class); + $this->quoteRepository = $this->getMockBuilder(CartRepositoryInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getForCustomer']) + ->getMockForAbstractClass(); + + $this->sessionQuote = $this->getMockBuilder(\Magento\Backend\Model\Session\Quote::class) + ->disableOriginalConstructor() + ->setMethods(['getQuote', 'getStoreId', 'getCustomerId']) + ->getMock(); + $this->customerMapper = $this->getMockBuilder(Mapper::class) ->setMethods(['toFlatArray']) ->disableOriginalConstructor() @@ -103,6 +125,8 @@ protected function setUp() 'quoteItemUpdater' => $this->itemUpdater, 'customerMapper' => $this->customerMapper, 'dataObjectHelper' => $this->dataObjectHelper, + 'quoteRepository' => $this->quoteRepository, + 'quoteFactory' => $this->quoteFactory, ] ); } @@ -264,4 +288,28 @@ public function testApplyCoupon() $object = $this->adminOrderCreate->applyCoupon($couponCode); self::assertEquals($this->adminOrderCreate, $object); } + + public function testGetCustomerCart() + { + $storeId = 2; + $customerId = 2; + $cartResult = [ + 'cart' => true, + ]; + + $this->quoteFactory->expects($this->once()) + ->method('create'); + $this->sessionQuote->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); + $this->sessionQuote->expects($this->once()) + ->method('getCustomerId') + ->willReturn($customerId); + $this->quoteRepository->expects($this->once()) + ->method('getForCustomer') + ->with($customerId, [$storeId]) + ->willReturn($cartResult); + + $this->assertEquals($cartResult, $this->adminOrderCreate->getCustomerCart()); + } } From e58f63a7d0822b39cfe128af8e1ca5fdc4694074 Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Tue, 10 Apr 2018 09:24:51 -0500 Subject: [PATCH 0075/2023] MAGETWO-88232: Images from WYSIWYG (Text, Slider) do not show up on admin preview nor storefront Unskip tests that were failing due to this issue (MAGETWO-88266) --- .../Catalog/Test/AdminAddImageToWYSIWYGCatalogCest.xml | 2 -- .../Catalog/Test/AdminAddImageToWYSIWYGProductCest.xml | 2 -- .../FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGBlockCest.xml | 2 -- .../Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml | 2 -- .../Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml | 2 -- 5 files changed, 10 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGCatalogCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGCatalogCest.xml index 8aa58cf1fb164..0f202e30c503f 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGCatalogCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGCatalogCest.xml @@ -21,8 +21,6 @@ - - diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGProductCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGProductCest.xml index ddc904d2ae396..0fc5f7cf8f960 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGProductCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageToWYSIWYGProductCest.xml @@ -16,8 +16,6 @@ - - diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGBlockCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGBlockCest.xml index 586be48618437..72d08737092cc 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGBlockCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGBlockCest.xml @@ -16,8 +16,6 @@ - - diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml index 626654b462833..da81fc5f96705 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml @@ -16,8 +16,6 @@ - - diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml index dcc9c798dc4c1..469139012cea3 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml @@ -16,8 +16,6 @@ - - From e06b032322940598c375a6df948d87df07f800c9 Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Tue, 10 Apr 2018 14:00:56 -0500 Subject: [PATCH 0076/2023] MAGETWO-88232: Images from WYSIWYG (Text, Slider) do not show up on admin preview nor storefront Revert Images helper and add fix to tinymce4adapter --- .../Magento/Cms/Helper/Wysiwyg/Images.php | 17 +-- .../Magento/Cms/Helper/Wysiwyg/ImagesTest.php | 110 ++++++++++++++++-- .../wysiwyg/tiny_mce/tinymce4Adapter.js | 4 +- 3 files changed, 111 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Cms/Helper/Wysiwyg/Images.php b/app/code/Magento/Cms/Helper/Wysiwyg/Images.php index a509b6009cad8..cd3473c6bab87 100644 --- a/app/code/Magento/Cms/Helper/Wysiwyg/Images.php +++ b/app/code/Magento/Cms/Helper/Wysiwyg/Images.php @@ -9,8 +9,6 @@ /** * Wysiwyg Images Helper. - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Images extends \Magento\Framework\App\Helper\AbstractHelper { @@ -213,15 +211,12 @@ public function getImageHtmlDeclaration($filename, $renderAsTag = false) $html = $fileUrl; } else { $directive = $this->urlEncoder->encode($directive); - $html = rtrim( - $this->_backendData->getUrl( - 'cms/wysiwyg/directive', - [ - '___directive' => $directive, - '_escape_params' => false, - ] - ), - '/' + $html = $this->_backendData->getUrl( + 'cms/wysiwyg/directive', + [ + '___directive' => $directive, + '_escape_params' => false, + ] ); } } diff --git a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php index 12d2a467360ea..b49ddc2d23285 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php @@ -6,9 +6,20 @@ namespace Magento\Cms\Helper\Wysiwyg; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\TestFramework\ObjectManager; class ImagesTest extends \PHPUnit\Framework\TestCase { + /** + * @var ObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + } + public function testGetStorageRoot() { /** @var \Magento\Framework\Filesystem $filesystem */ @@ -16,18 +27,103 @@ public function testGetStorageRoot() \Magento\Framework\Filesystem::class ); $mediaPath = $filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath(); - /** @var \Magento\Cms\Helper\Wysiwyg\Images $helper */ - $helper = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Cms\Helper\Wysiwyg\Images::class - ); + $helper = $this->generateHelper(); $this->assertStringStartsWith($mediaPath, $helper->getStorageRoot()); } public function testGetCurrentUrl() { - $helper = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Cms\Helper\Wysiwyg\Images::class - ); + $helper = $this->generateHelper(); $this->assertStringStartsWith('http://localhost/', $helper->getCurrentUrl()); } + + /** + * @param bool $staticUrlsAllowed + * @param string $filename + * @param bool $renderAsTag + * @param string|callable $expectedResult - string or callable to make unique assertions on $expectedResult + * + * @magentoConfigFixture current_store web/unsecure/base_url http://example.com/ + * @dataProvider providerGetImageHtmlDeclaration + */ + public function testGetImageHtmlDeclarationWithUsingStaticUrlsAllowed( + $staticUrlsAllowed, + $filename, + $renderAsTag, + $expectedResult + ) { + $helper = $this->generateHelper($staticUrlsAllowed); + + $actualResult = $helper->getImageHtmlDeclaration($filename, $renderAsTag); + + if (is_callable($expectedResult)) { + $expectedResult($actualResult); + } else { + $this->assertEquals( + $expectedResult, + $actualResult + ); + } + } + + public function providerGetImageHtmlDeclaration() + { + return [ + [true, 'wysiwyg/hello.png', true, ''], + [ + false, + 'wysiwyg/hello.png', + false, + function ($actualResult) { + $expectedResult = ( + '/backend/cms/wysiwyg/directive/___directive/' . + 'e3ttZWRpYSB1cmw9Ind5c2l3eWcvaGVsbG8ucG5nIn19/' + ); + + $this->assertEquals($expectedResult, parse_url($actualResult, PHP_URL_PATH)); + } + ], + [true, 'wysiwyg/hello.png', false, 'http://example.com/pub/media/wysiwyg/hello.png'], + [false, 'wysiwyg/hello.png', true, ''], + ]; + } + + /** + * Generate instance of Images Helper + * + * @param bool|null $staticUrlsAllowed - if boolean, mock is created to override value of isUsingStaticUrlsAllowed + * @return \Magento\Cms\Helper\Wysiwyg\Images + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + private function generateHelper($staticUrlsAllowed = null) + { + if (!is_bool($staticUrlsAllowed)) { + return $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class); + } + + $eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); + + $contextMock = $this->objectManager->create(\Magento\Framework\App\Helper\Context::class, [ + 'eventManager' => $eventManagerMock, + ]); + + $helper = $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class, [ + 'context' => $contextMock + ]); + + $storeId = 1; + $helper->setStoreId($storeId); + + $checkResult = new \stdClass(); + $checkResult->isAllowed = false; + + $eventManagerMock->expects($this->any()) + ->method('dispatch') + ->with('cms_wysiwyg_images_static_urls_allowed', ['result' => $checkResult, 'store_id' => $storeId]) + ->willReturnCallback(function ($_, $arr) use ($staticUrlsAllowed) { + $arr['result']->isAllowed = $staticUrlsAllowed; + }); + + return $helper; + } } diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js index bfae7a0157c23..443ca40862ca4 100644 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js @@ -608,10 +608,10 @@ define([ decodeDirectives: function (content) { // escape special chars in directives url to use it in regular expression var url = this.makeDirectiveUrl('%directive%').replace(/([$^.?*!+:=()\[\]{}|\\])/g, '\\$1'), - reg = new RegExp(url.replace('%directive%', '([a-zA-Z0-9,_-]+(?:%2[A-Z]|)+)')); + reg = new RegExp(url.replace('%directive%', '([a-zA-Z0-9,_-]+(?:%2[A-Z]|)+\/?)')); return content.gsub(reg, function (match) { //eslint-disable-line no-extra-bind - return Base64.mageDecode(decodeURIComponent(match[1])).replace(/"/g, '"'); + return Base64.mageDecode(decodeURIComponent(match[1]).replace(/\/$/, '')).replace(/"/g, '"'); }); }, From bba1ea190e63bd525bfa44cb8c4b39ceb5eb70ec Mon Sep 17 00:00:00 2001 From: John Stennett Date: Tue, 10 Apr 2018 14:13:20 -0500 Subject: [PATCH 0077/2023] MQE-920: MSI MFTF Test Cases 2 - Removing an unnecessary waitForPageLoad in an Action Group since the element contains a "timeout" value. - Adding additional elements to the Grid section. - Adding "timeout" values to elements that trigger page loads when clicked. i.e. "Save" buttons. - Adding additional buttons that appear on the Stores page for creating different entites. - Adding a section for the New Websites form. --- .../Config/Section/StoreConfigSection.xml | 2 +- ...minCreateProductConfigurationsPanelSection.xml | 1 + .../Store/Section/AdminNewStoreGroupSection.xml | 1 + .../Store/Section/AdminNewWebsiteSection.xml | 15 +++++++++++++++ .../Store/Section/AdminStoresGridSection.xml | 9 +++++++-- .../Section/AdminStoresMainActionsSection.xml | 10 +++++----- .../AdminDataGridFilterActionGroup.xml | 1 - .../Ui/Section/AdminGridControlsSection.xml | 1 + 8 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewWebsiteSection.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Section/StoreConfigSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Section/StoreConfigSection.xml index e7bee71c88952..6580d41c06d49 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Section/StoreConfigSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Section/StoreConfigSection.xml @@ -12,6 +12,6 @@ - +
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminCreateProductConfigurationsPanelSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminCreateProductConfigurationsPanelSection.xml index 9f17d86044244..737d2b7cd0740 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminCreateProductConfigurationsPanelSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminCreateProductConfigurationsPanelSection.xml @@ -15,6 +15,7 @@ + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewStoreGroupSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewStoreGroupSection.xml index fd2563586b303..7357ee0771239 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewStoreGroupSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewStoreGroupSection.xml @@ -7,6 +7,7 @@ -->
+ diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewWebsiteSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewWebsiteSection.xml new file mode 100644 index 0000000000000..1195d1c76b0cd --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewWebsiteSection.xml @@ -0,0 +1,15 @@ + + + + +
+ + +
+
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminStoresGridSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminStoresGridSection.xml index b28f9c37485fb..86ba480202b50 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminStoresGridSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminStoresGridSection.xml @@ -6,6 +6,11 @@ */ --> +
+ + + +
@@ -15,6 +20,6 @@ - -
+ +
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminStoresMainActionsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminStoresMainActionsSection.xml index d63d5df51ccf8..95d6d87ccc184 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminStoresMainActionsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminStoresMainActionsSection.xml @@ -7,10 +7,10 @@ -->
- - - - - + + + + +
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/ActionGroup/AdminDataGridFilterActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/ActionGroup/AdminDataGridFilterActionGroup.xml index c3611eae11ffc..db89951690fc2 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/ActionGroup/AdminDataGridFilterActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/ActionGroup/AdminDataGridFilterActionGroup.xml @@ -15,7 +15,6 @@
- diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/Section/AdminGridControlsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/Section/AdminGridControlsSection.xml index 71f8682e55bee..7adc9a193a9c6 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/Section/AdminGridControlsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/Section/AdminGridControlsSection.xml @@ -40,6 +40,7 @@
+
From 6efb1a57405b46464ee692d996220ed497993016 Mon Sep 17 00:00:00 2001 From: John Stennett Date: Tue, 10 Apr 2018 14:19:10 -0500 Subject: [PATCH 0078/2023] MQE-920: MSI MFTF Test Cases 2 - Adding additional sections to the Configurable Product page. --- .../AdminProductFormConfigurationsSection.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminProductFormConfigurationsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminProductFormConfigurationsSection.xml index 21f9611980c77..93ff9f4a2b0ad 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminProductFormConfigurationsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminProductFormConfigurationsSection.xml @@ -17,4 +17,20 @@
+
+ + + +
+
+ +
+
+ + + +
+
+ +
From 4f9e10607eb5420f126df58dc692a56cb8bafc60 Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Tue, 10 Apr 2018 14:22:09 -0500 Subject: [PATCH 0079/2023] MAGETWO-88232: Images from WYSIWYG (Text, Slider) do not show up on admin preview nor storefront Refactor --- .../testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php index b49ddc2d23285..2a20b6cd295ff 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php @@ -46,7 +46,7 @@ public function testGetCurrentUrl() * @magentoConfigFixture current_store web/unsecure/base_url http://example.com/ * @dataProvider providerGetImageHtmlDeclaration */ - public function testGetImageHtmlDeclarationWithUsingStaticUrlsAllowed( + public function testGetImageHtmlDeclaration( $staticUrlsAllowed, $filename, $renderAsTag, @@ -66,6 +66,11 @@ public function testGetImageHtmlDeclarationWithUsingStaticUrlsAllowed( } } + /** + * Data provider for testGetImageHtmlDeclaration + * + * @return array + */ public function providerGetImageHtmlDeclaration() { return [ From f5f0bff8dc2aac93b21cbcd0d9301c828865b8bd Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Tue, 10 Apr 2018 14:42:38 -0500 Subject: [PATCH 0080/2023] MAGETWO-88232: Images from WYSIWYG (Text, Slider) do not show up on admin preview nor storefront Add wysiwygAdapter.test.js --- .../tests/lib/mage/wysiwygAdapter.test.js | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 dev/tests/js/jasmine/tests/lib/mage/wysiwygAdapter.test.js diff --git a/dev/tests/js/jasmine/tests/lib/mage/wysiwygAdapter.test.js b/dev/tests/js/jasmine/tests/lib/mage/wysiwygAdapter.test.js new file mode 100644 index 0000000000000..a402ea29040aa --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/wysiwygAdapter.test.js @@ -0,0 +1,57 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/* eslint-disable max-nested-callbacks */ +define([ + 'wysiwygAdapter' +], function (wysiwygAdapter) { + 'use strict'; + + var obj; + + beforeEach(function () { + var Constr = function () {}; + + Constr.prototype = wysiwygAdapter; + + obj = new Constr(); + obj.initialize('id', { + 'directives_url': 'http://example.com/admin/cms/wysiwyg/directive/' + }); + }); + + describe('wysiwygAdapter', function () { + var decodedHtml = '

' + + '

', + encodedHtml = '

' + + '' + + '

', + encodedHtmlWithForwardSlashInImgSrc = encodedHtml.replace('%2C%2C', '%2C%2C/'); + + describe('"encodeDirectives" method', function () { + it('converts media directive img src to directive URL', function () { + expect(obj.encodeDirectives(decodedHtml)).toEqual(encodedHtml); + }); + }); + + describe('"decodeDirectives" method', function () { + it( + 'converts directive URL img src without a trailing forward slash ' + + 'to media url without a trailing forward slash', + function () { + expect(obj.decodeDirectives(encodedHtml)).toEqual(decodedHtml); + } + ); + + it('converts directive URL img src with a trailing forward slash ' + + 'to media url without a trailing forward slash', + function () { + expect(obj.decodeDirectives(encodedHtmlWithForwardSlashInImgSrc)).toEqual(decodedHtml); + } + ); + }); + }); +}); From 128eea34b3fc5b1fd1d394722a9dd371a654e41c Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Tue, 10 Apr 2018 14:57:57 -0500 Subject: [PATCH 0081/2023] MAGETWO-88232: Images from WYSIWYG (Text, Slider) do not show up on admin preview nor storefront Add docblock --- dev/tests/js/jasmine/tests/lib/mage/wysiwygAdapter.test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/tests/js/jasmine/tests/lib/mage/wysiwygAdapter.test.js b/dev/tests/js/jasmine/tests/lib/mage/wysiwygAdapter.test.js index a402ea29040aa..ff510046e5528 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/wysiwygAdapter.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/wysiwygAdapter.test.js @@ -12,6 +12,11 @@ define([ var obj; beforeEach(function () { + + /** + * Dummy constructor to use for instantiation + * @constructor + */ var Constr = function () {}; Constr.prototype = wysiwygAdapter; From 33a003c846a615fa6c2bb266073203f46371caa2 Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Tue, 10 Apr 2018 15:32:15 -0500 Subject: [PATCH 0082/2023] MAGETWO-88232: Images from WYSIWYG (Text, Slider) do not show up on admin preview nor storefront Refactor ImagesTest --- .../Magento/Cms/Helper/Wysiwyg/ImagesTest.php | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php index 2a20b6cd295ff..16a6a66e25bd7 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php @@ -27,32 +27,34 @@ public function testGetStorageRoot() \Magento\Framework\Filesystem::class ); $mediaPath = $filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath(); - $helper = $this->generateHelper(); + $helper = $this->generateHelper(null); $this->assertStringStartsWith($mediaPath, $helper->getStorageRoot()); } + /** + * @magentoConfigFixture current_store web/unsecure/base_url http://example.com/ + */ public function testGetCurrentUrl() { - $helper = $this->generateHelper(); - $this->assertStringStartsWith('http://localhost/', $helper->getCurrentUrl()); + $helper = $this->generateHelper(null); + $this->assertStringStartsWith('http://example.com/', $helper->getCurrentUrl()); } /** - * @param bool $staticUrlsAllowed + * @param bool $isStaticUrlsAllowed * @param string $filename * @param bool $renderAsTag * @param string|callable $expectedResult - string or callable to make unique assertions on $expectedResult - * * @magentoConfigFixture current_store web/unsecure/base_url http://example.com/ * @dataProvider providerGetImageHtmlDeclaration */ public function testGetImageHtmlDeclaration( - $staticUrlsAllowed, + $isStaticUrlsAllowed, $filename, $renderAsTag, $expectedResult ) { - $helper = $this->generateHelper($staticUrlsAllowed); + $helper = $this->generateHelper($isStaticUrlsAllowed); $actualResult = $helper->getImageHtmlDeclaration($filename, $renderAsTag); @@ -96,38 +98,39 @@ function ($actualResult) { /** * Generate instance of Images Helper * - * @param bool|null $staticUrlsAllowed - if boolean, mock is created to override value of isUsingStaticUrlsAllowed + * @param bool|null $isStaticUrlsAllowed - if boolean, mock is created to override value of isUsingStaticUrlsAllowed * @return \Magento\Cms\Helper\Wysiwyg\Images * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ - private function generateHelper($staticUrlsAllowed = null) + private function generateHelper($isStaticUrlsAllowed = false) { - if (!is_bool($staticUrlsAllowed)) { - return $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class); - } + $storeId = 1; - $eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); + if (!is_bool($isStaticUrlsAllowed)) { + $helper = $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class); + } else { + $eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); - $contextMock = $this->objectManager->create(\Magento\Framework\App\Helper\Context::class, [ - 'eventManager' => $eventManagerMock, - ]); + $contextMock = $this->objectManager->create(\Magento\Framework\App\Helper\Context::class, [ + 'eventManager' => $eventManagerMock, + ]); - $helper = $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class, [ - 'context' => $contextMock - ]); + $helper = $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class, [ + 'context' => $contextMock + ]); - $storeId = 1; - $helper->setStoreId($storeId); + $checkResult = new \stdClass(); + $checkResult->isAllowed = false; - $checkResult = new \stdClass(); - $checkResult->isAllowed = false; + $eventManagerMock->expects($this->any()) + ->method('dispatch') + ->with('cms_wysiwyg_images_static_urls_allowed', ['result' => $checkResult, 'store_id' => $storeId]) + ->willReturnCallback(function ($_, $arr) use ($isStaticUrlsAllowed) { + $arr['result']->isAllowed = $isStaticUrlsAllowed; + }); + } - $eventManagerMock->expects($this->any()) - ->method('dispatch') - ->with('cms_wysiwyg_images_static_urls_allowed', ['result' => $checkResult, 'store_id' => $storeId]) - ->willReturnCallback(function ($_, $arr) use ($staticUrlsAllowed) { - $arr['result']->isAllowed = $staticUrlsAllowed; - }); + $helper->setStoreId($storeId); return $helper; } From fe3f23bb2c0f767b43574a20e698ac447c01e0f4 Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Tue, 10 Apr 2018 15:47:55 -0500 Subject: [PATCH 0083/2023] MAGETWO-88232: Images from WYSIWYG (Text, Slider) do not show up on admin preview nor storefront Refactor ImagesTest to prevent calling of generateHelper on previously existing tests --- .../Magento/Cms/Helper/Wysiwyg/ImagesTest.php | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php index 16a6a66e25bd7..96c717598534d 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php @@ -27,7 +27,10 @@ public function testGetStorageRoot() \Magento\Framework\Filesystem::class ); $mediaPath = $filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath(); - $helper = $this->generateHelper(null); + /** @var \Magento\Cms\Helper\Wysiwyg\Images $helper */ + $helper = $this->objectManager->create( + \Magento\Cms\Helper\Wysiwyg\Images::class + ); $this->assertStringStartsWith($mediaPath, $helper->getStorageRoot()); } @@ -36,7 +39,10 @@ public function testGetStorageRoot() */ public function testGetCurrentUrl() { - $helper = $this->generateHelper(null); + /** @var \Magento\Cms\Helper\Wysiwyg\Images $helper */ + $helper = $this->objectManager->create( + \Magento\Cms\Helper\Wysiwyg\Images::class + ); $this->assertStringStartsWith('http://example.com/', $helper->getCurrentUrl()); } @@ -98,7 +104,7 @@ function ($actualResult) { /** * Generate instance of Images Helper * - * @param bool|null $isStaticUrlsAllowed - if boolean, mock is created to override value of isUsingStaticUrlsAllowed + * @param bool $isStaticUrlsAllowed - mock is created to override value of isUsingStaticUrlsAllowed method in class * @return \Magento\Cms\Helper\Wysiwyg\Images * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ @@ -106,29 +112,25 @@ private function generateHelper($isStaticUrlsAllowed = false) { $storeId = 1; - if (!is_bool($isStaticUrlsAllowed)) { - $helper = $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class); - } else { - $eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); + $eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); - $contextMock = $this->objectManager->create(\Magento\Framework\App\Helper\Context::class, [ - 'eventManager' => $eventManagerMock, - ]); + $contextMock = $this->objectManager->create(\Magento\Framework\App\Helper\Context::class, [ + 'eventManager' => $eventManagerMock, + ]); - $helper = $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class, [ - 'context' => $contextMock - ]); + $helper = $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class, [ + 'context' => $contextMock + ]); - $checkResult = new \stdClass(); - $checkResult->isAllowed = false; + $checkResult = new \stdClass(); + $checkResult->isAllowed = false; - $eventManagerMock->expects($this->any()) - ->method('dispatch') - ->with('cms_wysiwyg_images_static_urls_allowed', ['result' => $checkResult, 'store_id' => $storeId]) - ->willReturnCallback(function ($_, $arr) use ($isStaticUrlsAllowed) { - $arr['result']->isAllowed = $isStaticUrlsAllowed; - }); - } + $eventManagerMock->expects($this->any()) + ->method('dispatch') + ->with('cms_wysiwyg_images_static_urls_allowed', ['result' => $checkResult, 'store_id' => $storeId]) + ->willReturnCallback(function ($_, $arr) use ($isStaticUrlsAllowed) { + $arr['result']->isAllowed = $isStaticUrlsAllowed; + }); $helper->setStoreId($storeId); From 43aaaffb8a827f6adf64efb30196099fd523de6b Mon Sep 17 00:00:00 2001 From: Kieu Phan Date: Tue, 10 Apr 2018 16:35:58 -0500 Subject: [PATCH 0084/2023] MAGETWO-90224: Automate MFTF --- .../Magento/FunctionalTest/Cms/Data/CmsPageData.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Data/CmsPageData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Data/CmsPageData.xml index 324d937df95b6..38567beed846a 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Data/CmsPageData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Data/CmsPageData.xml @@ -14,6 +14,12 @@ Sample page content. Yada yada yada. test-page- + + Test CMS Page + Test Content Heading + Sample page content. Yada yada yada. + test-page- + testpage Test Content Heading From 8e890b9a8458a57eb4256f5859e508ec7c317d51 Mon Sep 17 00:00:00 2001 From: Viktor Sevch Date: Wed, 11 Apr 2018 10:26:58 +0300 Subject: [PATCH 0085/2023] MAGETWO-82055: [2.3] - PayPal Express doesn't show up in checkout --- .../Paypal/view/frontend/layout/checkout_index_index.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/code/Magento/Paypal/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Paypal/view/frontend/layout/checkout_index_index.xml index 4f514806eeb89..73c44faff5a57 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/checkout_index_index.xml @@ -44,6 +44,15 @@ true + + false + + + false + + + false + From aaa2818f03399db1a9ab305dd5b243c20cf29be2 Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Wed, 11 Apr 2018 14:51:04 +0300 Subject: [PATCH 0086/2023] MAGETWO-89009: Split database doesn't work on 2.3-develop --- .../Magento/GiftMessage/etc/db_schema.xml | 8 +- .../Magento/OfflineShipping/etc/db_schema.xml | 6 +- app/code/Magento/Paypal/etc/db_schema.xml | 2 +- app/code/Magento/Persistent/etc/db_schema.xml | 2 +- app/code/Magento/Quote/etc/db_schema.xml | 16 ++-- app/code/Magento/Signifyd/etc/db_schema.xml | 2 +- app/code/Magento/Weee/etc/db_schema.xml | 2 +- .../Schema/DataSavior/SelectGenerator.php | 4 +- .../Schema/Db/DDLTriggerInterface.php | 6 +- .../DDL/Triggers/MigrateDataBetweenShards.php | 84 +++++++++++++++++++ .../Db/MySQL/DDL/Triggers/MigrateDataFrom.php | 6 +- .../Declaration/Schema/Diff/DiffManager.php | 35 +++++--- .../Declaration/Schema/Diff/TableDiff.php | 5 ++ .../Setup/Declaration/Schema/Dto/Table.php | 22 ++++- .../Declaration/Schema/OperationInterface.php | 4 +- .../Schema/Operations/AddColumn.php | 10 ++- .../Schema/Operations/CreateTable.php | 34 +++++++- .../Schema/Operations/ReCreateTable.php | 30 ++++++- .../Setup/Declaration/Schema/etc/schema.xsd | 2 +- 19 files changed, 226 insertions(+), 54 deletions(-) create mode 100644 lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataBetweenShards.php diff --git a/app/code/Magento/GiftMessage/etc/db_schema.xml b/app/code/Magento/GiftMessage/etc/db_schema.xml index ecd73bd8708f0..518c6398e4c8d 100644 --- a/app/code/Magento/GiftMessage/etc/db_schema.xml +++ b/app/code/Magento/GiftMessage/etc/db_schema.xml @@ -19,19 +19,19 @@ - +
- +
- +
- +
diff --git a/app/code/Magento/OfflineShipping/etc/db_schema.xml b/app/code/Magento/OfflineShipping/etc/db_schema.xml index 1a4ecd89582c6..80f4b56a1723d 100644 --- a/app/code/Magento/OfflineShipping/etc/db_schema.xml +++ b/app/code/Magento/OfflineShipping/etc/db_schema.xml @@ -45,15 +45,15 @@ - +
- +
- +
diff --git a/app/code/Magento/Paypal/etc/db_schema.xml b/app/code/Magento/Paypal/etc/db_schema.xml index f6f5448dbc2f0..2703ee4f5be30 100644 --- a/app/code/Magento/Paypal/etc/db_schema.xml +++ b/app/code/Magento/Paypal/etc/db_schema.xml @@ -145,7 +145,7 @@ - +
diff --git a/app/code/Magento/Persistent/etc/db_schema.xml b/app/code/Magento/Persistent/etc/db_schema.xml index 31adf5be6f0c4..68678fc60f096 100644 --- a/app/code/Magento/Persistent/etc/db_schema.xml +++ b/app/code/Magento/Persistent/etc/db_schema.xml @@ -37,7 +37,7 @@
- +
diff --git a/app/code/Magento/Quote/etc/db_schema.xml b/app/code/Magento/Quote/etc/db_schema.xml index ff127b9c06f0e..999d23328e0ec 100644 --- a/app/code/Magento/Quote/etc/db_schema.xml +++ b/app/code/Magento/Quote/etc/db_schema.xml @@ -7,7 +7,7 @@ --> - +
- +
- +
- +
- +
- +
- +
- +
- +
diff --git a/app/code/Magento/Weee/etc/db_schema.xml b/app/code/Magento/Weee/etc/db_schema.xml index 71d957ecaf5b8..96c3be9740e56 100644 --- a/app/code/Magento/Weee/etc/db_schema.xml +++ b/app/code/Magento/Weee/etc/db_schema.xml @@ -48,7 +48,7 @@ - +
diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/DataSavior/SelectGenerator.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/DataSavior/SelectGenerator.php index 9e560acf1f62a..08da74fb6a2b6 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/DataSavior/SelectGenerator.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/DataSavior/SelectGenerator.php @@ -17,7 +17,7 @@ class SelectGenerator /** * @var int */ - private $batchSize = 12000; + private $batchSize = 30000; /** * @var int @@ -36,7 +36,7 @@ class SelectGenerator */ public function __construct( ResourceConnection $resourceConnection, - $baseBatchSize = 15000 + $baseBatchSize = 30000 ) { $this->baseBatchSize = $baseBatchSize; $this->resourceConnection = $resourceConnection; diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/DDLTriggerInterface.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/DDLTriggerInterface.php index fa074d4ba16d3..54dfe72b5db36 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/DDLTriggerInterface.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/DDLTriggerInterface.php @@ -6,7 +6,7 @@ namespace Magento\Framework\Setup\Declaration\Schema\Db; -use Magento\Framework\Setup\Declaration\Schema\Dto\ElementInterface; +use Magento\Framework\Setup\Declaration\Schema\ElementHistory; /** * DDL triggers is events that can be fired: @@ -30,8 +30,8 @@ public function isApplicable($statement); /** * Setup callback to current statement, can generate new statements. * - * @param ElementInterface $element + * @param ElementHistory $elementHistory * @return callable */ - public function getCallback(ElementInterface $element); + public function getCallback(ElementHistory $elementHistory); } diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataBetweenShards.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataBetweenShards.php new file mode 100644 index 0000000000000..ad23afb66751b --- /dev/null +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataBetweenShards.php @@ -0,0 +1,84 @@ +resourceConnection = $resourceConnection; + $this->selectGenerator = $selectGenerator; + } + + /** + * If skip migration flag is enabled, we should skip data migration + * + * @inheritdoc + */ + public function isApplicable($statement) + { + return $statement !== self::SKIP_MIGRATION_DATA_FLAG; + } + + /** + * @inheritdoc + */ + public function getCallback(ElementHistory $elementHistory) + { + /** @var Table $newTable */ + $newTable = $elementHistory->getNew(); + /** @var Table $oldTable */ + $oldTable = $elementHistory->getOld(); + $that = $this; + + return function () use ($newTable, $oldTable, $that) { + $firstConnection = $that->resourceConnection->getConnection($oldTable->getResource()); + $secondConnection = $that->resourceConnection->getConnection($newTable->getResource()); + $select = $firstConnection->select()->from($oldTable->getName()); + + foreach ($this->selectGenerator->generator($select, $oldTable->getResource()) as $data) { + if (count($data)) { + $columns = array_keys($data[0]); + $secondConnection->insertArray($newTable->getName(), $columns, $data); + } + } + }; + } +} diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFrom.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFrom.php index b2cc0f4d91379..293a39fc500eb 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFrom.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFrom.php @@ -11,6 +11,7 @@ use Magento\Framework\Setup\Declaration\Schema\Db\DDLTriggerInterface; use Magento\Framework\Setup\Declaration\Schema\Dto\Column; use Magento\Framework\Setup\Declaration\Schema\Dto\ElementInterface; +use Magento\Framework\Setup\Declaration\Schema\ElementHistory; /** * Used to migrate data from one column to another in scope of one table. @@ -47,11 +48,12 @@ public function isApplicable($statement) } /** - * @param Column $column * @inheritdoc */ - public function getCallback(ElementInterface $column) + public function getCallback(ElementHistory $columnHistory) { + /** @var Column $column */ + $column = $columnHistory->getNew(); preg_match(self::MATCH_PATTERN, $column->getOnCreate(), $matches); return function () use ($column, $matches) { $tableName = $column->getTable()->getName(); diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Diff/DiffManager.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Diff/DiffManager.php index 9a268d0eaa9d0..07d2a4731721d 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Diff/DiffManager.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Diff/DiffManager.php @@ -171,19 +171,28 @@ public function registerReferenceDrop(Reference $reference, Diff $diff) */ public function registerTableModification(Table $declaredTable, Table $generatedTable, Diff $diff) { - if ($declaredTable->getResource() !== $generatedTable->getResource()) { - $diff->register( - $declaredTable, - ReCreateTable::OPERATION_NAME, - $generatedTable - ); - } else { - $diff->register( - $declaredTable, - ModifyTable::OPERATION_NAME, - $generatedTable - ); - } + $diff->register( + $declaredTable, + ModifyTable::OPERATION_NAME, + $generatedTable + ); + } + + /** + * Register recreation of table, in case for example, when we need to move table from one shard to another + * + * @param Table $declaredTable + * @param Table $generatedTable + * @param Diff $diff + * @return void + */ + public function registerRecreation(Table $declaredTable, Table $generatedTable, Diff $diff) + { + $diff->register( + $declaredTable, + ReCreateTable::OPERATION_NAME, + $generatedTable + ); } /** diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Diff/TableDiff.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Diff/TableDiff.php index 73a1d86f262ad..2030b192935e7 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Diff/TableDiff.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Diff/TableDiff.php @@ -126,6 +126,11 @@ public function diff( ElementInterface $generatedTable, Diff $diff ) { + if ($declaredTable->getResource() !== $generatedTable->getResource()) { + $this->diffManager->registerRecreation($declaredTable, $generatedTable, $diff); + return $diff; + } + if ($this->diffManager->shouldBeModified($declaredTable, $generatedTable)) { $this->diffManager->registerTableModification($declaredTable, $generatedTable, $diff); } diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Table.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Table.php index 76b87ea8fc886..f7d8b25c24bab 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Table.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Dto/Table.php @@ -64,16 +64,22 @@ class Table extends GenericElement implements */ private $comment; + /** + * @var string + */ + private $onCreate; + /** * @param string $name - * @param string $nameWithoutPrefix * @param string $type + * @param string $nameWithoutPrefix * @param string $resource * @param string $engine * @param string|null $comment * @param array $columns * @param array $indexes * @param array $constraints + * @param string $onCreate * @internal param string $nameWithPrefix */ public function __construct( @@ -85,7 +91,8 @@ public function __construct( string $comment = null, array $columns = [], array $indexes = [], - array $constraints = [] + array $constraints = [], + string $onCreate = '' ) { parent::__construct($name, $type); $this->columns = $columns; @@ -95,6 +102,7 @@ public function __construct( $this->engine = $engine; $this->nameWithoutPrefix = $nameWithoutPrefix; $this->comment = $comment; + $this->onCreate = $onCreate; } /** @@ -212,6 +220,16 @@ public function addColumns(array $columns) $this->columns = array_replace($this->columns, $columns); } + /** + * Retrieve information about trigger + * + * @return string + */ + public function getOnCreate() + { + return $this->onCreate; + } + /** * If column exists - retrieve column * diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/OperationInterface.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/OperationInterface.php index 00490a96047df..5b7c97a4ef8ce 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/OperationInterface.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/OperationInterface.php @@ -6,6 +6,8 @@ namespace Magento\Framework\Setup\Declaration\Schema; +use Magento\Framework\Setup\Declaration\Schema\Db\Statement; + /** * Schema operation interface. */ @@ -34,7 +36,7 @@ public function isOperationDestructive(); * Apply change of any type. * * @param ElementHistory $elementHistory - * @return array + * @return Statement[] */ public function doOperation(ElementHistory $elementHistory); } diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/AddColumn.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/AddColumn.php index 5810c78a2093c..774e0b410de9b 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/AddColumn.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/AddColumn.php @@ -148,15 +148,17 @@ private function columnIsAutoIncrement(Column $column) * Setup triggers if column have onCreate syntax. * * @param Statement $statement - * @param Column $column + * @param ElementHistory $elementHistory * @return array */ - private function setupTriggersIfExists(Statement $statement, Column $column) + private function setupTriggersIfExists(Statement $statement, ElementHistory $elementHistory) { + /** @var Column $column */ + $column = $elementHistory->getNew(); //Add triggers to column foreach ($this->triggers as $ddlTrigger) { if ($ddlTrigger->isApplicable($column->getOnCreate())) { - $statement->addTrigger($ddlTrigger->getCallback($column)); + $statement->addTrigger($ddlTrigger->getCallback($elementHistory)); } } $statements = [$statement]; @@ -201,7 +203,7 @@ public function doOperation(ElementHistory $elementHistory) $definition, Column::TYPE ); - $statements = $this->setupTriggersIfExists($statement, $element); + $statements = $this->setupTriggersIfExists($statement, $elementHistory); if ($this->columnIsAutoIncrement($element)) { /** We need to reset auto_increment as new field should goes from 1 */ diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/CreateTable.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/CreateTable.php index 18726001c19f6..7ba8d55f48f19 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/CreateTable.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/CreateTable.php @@ -15,6 +15,7 @@ use Magento\Framework\Setup\Declaration\Schema\Dto\Index; use Magento\Framework\Setup\Declaration\Schema\Dto\Table; use Magento\Framework\Setup\Declaration\Schema\ElementHistory; +use Magento\Framework\Setup\Declaration\Schema\ElementHistoryFactory; use Magento\Framework\Setup\Declaration\Schema\OperationInterface; /** @@ -42,21 +43,29 @@ class CreateTable implements OperationInterface */ private $triggers; + /** + * @var ElementHistoryFactory + */ + private $elementHistoryFactory; + /** * Constructor. * * @param DbSchemaWriterInterface $dbSchemaWriter * @param DefinitionAggregator $definitionAggregator + * @param ElementHistoryFactory $elementHistoryFactory * @param array $triggers */ public function __construct( DbSchemaWriterInterface $dbSchemaWriter, DefinitionAggregator $definitionAggregator, + ElementHistoryFactory $elementHistoryFactory, array $triggers = [] ) { $this->dbSchemaWriter = $dbSchemaWriter; $this->definitionAggregator = $definitionAggregator; $this->triggers = $triggers; + $this->elementHistoryFactory = $elementHistoryFactory; } /** @@ -75,13 +84,28 @@ public function isOperationDestructive() return false; } + /** + * In some cases according to backward compatibility we want to use old table, + * for example in case of table recreation or table renaming + * + * We need to use definition of old table in order to prevent removal of 3-rd party columns, indexes, etc.. + * added not with declarative schema + * + * @param ElementHistory $elementHistory + * @return ElementInterface + */ + private function prepareTable(ElementHistory $elementHistory) : ElementInterface + { + return $elementHistory->getOld() ? $elementHistory->getOld() : $elementHistory->getNew(); + } + /** * {@inheritdoc} */ public function doOperation(ElementHistory $elementHistory) { /** @var Table $table */ - $table = $elementHistory->getNew(); + $table = $this->prepareTable($elementHistory); $definition = []; $data = [ Column::TYPE => $table->getColumns(), @@ -102,7 +126,7 @@ public function doOperation(ElementHistory $elementHistory) $createTableStatement = $this->dbSchemaWriter ->createTable( $table->getName(), - $table->getResource(), + $elementHistory->getNew()->getResource(), $definition, ['engine' => $table->getEngine(), 'comment' => $table->getComment()] ); @@ -111,8 +135,12 @@ public function doOperation(ElementHistory $elementHistory) foreach ($table->getColumns() as $column) { foreach ($this->triggers as $trigger) { if ($trigger->isApplicable($column->getOnCreate())) { + $elementHistory = $this->elementHistoryFactory->create([ + 'new' => $column, + 'old' => $column + ]); $createTableStatement->addTrigger( - $trigger->getCallback($column) + $trigger->getCallback($elementHistory) ); } } diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/ReCreateTable.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/ReCreateTable.php index a06c7c10325f5..b49d8771ca1f4 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/ReCreateTable.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Operations/ReCreateTable.php @@ -6,6 +6,9 @@ namespace Magento\Framework\Setup\Declaration\Schema\Operations; +use Magento\Framework\Setup\Declaration\Schema\Db\MySQL\DDL\Triggers\MigrateDataBetweenShards; +use Magento\Framework\Setup\Declaration\Schema\Db\Statement; +use Magento\Framework\Setup\Declaration\Schema\Dto\Table; use Magento\Framework\Setup\Declaration\Schema\ElementHistory; use Magento\Framework\Setup\Declaration\Schema\OperationInterface; @@ -30,16 +33,26 @@ class ReCreateTable implements OperationInterface */ private $dropTable; + /** + * @var MigrateDataBetweenShards + */ + private $migrateDataBetweenShards; + /** * Constructor. * * @param CreateTable $createTable * @param DropTable $dropTable + * @param MigrateDataBetweenShards $migrateDataBetweenShards */ - public function __construct(CreateTable $createTable, DropTable $dropTable) - { + public function __construct( + CreateTable $createTable, + DropTable $dropTable, + MigrateDataBetweenShards $migrateDataBetweenShards + ) { $this->createTable = $createTable; $this->dropTable = $dropTable; + $this->migrateDataBetweenShards = $migrateDataBetweenShards; } /** @@ -63,7 +76,16 @@ public function getOperationName() */ public function doOperation(ElementHistory $elementHistory) { - $statement = $this->dropTable->doOperation($elementHistory); - return array_merge($statement, $this->createTable->doOperation($elementHistory)); + /** @var Table $table */ + $table = $elementHistory->getNew(); + $statements = $this->createTable->doOperation($elementHistory); + /** @var Statement $statement */ + foreach ($statements as $statement) { + if ($this->migrateDataBetweenShards->isApplicable($table->getOnCreate())) { + $statement->addTrigger($this->migrateDataBetweenShards->getCallback($elementHistory)); + } + } + + return array_merge($statements, $this->dropTable->doOperation($elementHistory)); } } diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/schema.xsd b/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/schema.xsd index fa1894bb486cf..c237e7defb866 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/schema.xsd +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/etc/schema.xsd @@ -64,7 +64,7 @@ - + From 16a9ebdd237d3e6376435df21c8ccae8c48e4bf6 Mon Sep 17 00:00:00 2001 From: DianaRusin Date: Wed, 11 Apr 2018 15:55:40 +0300 Subject: [PATCH 0087/2023] MAGETWO-58213: [GITHUB] Configurable products import doesn't work configurable_variations not imported #5876 --- .../Import/Product/Type/Configurable.php | 2 +- .../Import/Product/Type/ConfigurableTest.php | 62 +++++++++---------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php index 6b168dcc2b458..b6b9f23e8df07 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php @@ -470,9 +470,9 @@ protected function _processSuperData() * @param array $rowData * * @return array + * @throws LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) - * @throws LocalizedException */ protected function _parseVariations($rowData) { diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/Product/Type/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/Product/Type/ConfigurableTest.php index c4b94e223ebd0..c39e03773c356 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/Product/Type/ConfigurableTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/Product/Type/ConfigurableTest.php @@ -156,6 +156,7 @@ public function testConfigurableImport($pathToFile, $productName, $optionSkuList * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php * @magentoAppArea adminhtml * @magentoAppIsolation enabled + * @return void */ public function testConfigurableImportWithMultipleStores() { @@ -176,23 +177,21 @@ public function testConfigurableImportWithMultipleStores() 'directory' => $directory, ] ); - $errors = $this->model->setSource( - $source - )->setParameters( + $errors = $this->model->setSource($source)->setParameters( [ 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product', ] )->validateData(); - $this->assertTrue($errors->getErrorsCount() == 0); + $this->assertTrue($errors->getErrorsCount() === 0); $this->model->importData(); foreach ($products as $storeCode => $productName) { $store = $this->objectManager->create(\Magento\Store\Model\Store::class); $store->load($storeCode, 'code'); - /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ - $productRepository = $this->objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); /** @var \Magento\Catalog\Api\Data\ProductInterface $product */ $product = $productRepository->get($productSku, 0, $store->getId()); $this->assertFalse($product->isObjectNew()); @@ -206,35 +205,32 @@ public function testConfigurableImportWithMultipleStores() * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php * @magentoDbIsolation disabled * @magentoAppArea adminhtml + * @return void */ public function testConfigurableImportWithStoreSpecifiedMainItem() { - { - $expectedErrorMessage = 'Product with assigned super attributes should not have specified "store_view_code"' - . ' value'; - $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/import_configurable_for_multiple_store_views_error.csv', - 'directory' => $directory, - ] - ); - $errors = $this->model->setSource( - $source - )->setParameters( - [ - 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, - 'entity' => 'catalog_product', - ] - )->validateData(); - - $this->assertTrue($errors->getErrorsCount() == 1); - $this->assertEquals($expectedErrorMessage, $errors->getAllErrors()[0]->getErrorMessage()); - } + $expectedErrorMessage = 'Product with assigned super attributes should not have specified "store_view_code"' + . ' value'; + $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/import_configurable_for_multiple_store_views_error.csv', + 'directory' => $directory, + ] + ); + $errors = $this->model->setSource($source)->setParameters( + [ + 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, + 'entity' => 'catalog_product', + ] + )->validateData(); + + $this->assertTrue($errors->getErrorsCount() === 1); + $this->assertEquals($expectedErrorMessage, $errors->getAllErrors()[0]->getErrorMessage()); } } From c2641b576e01a1bcd3618cc222ae823cecd6a54e Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Wed, 11 Apr 2018 17:00:53 +0300 Subject: [PATCH 0088/2023] MAGETWO-90055: When querying for products filtered by category_id, response has all_children = null for categories --- app/code/Magento/CatalogGraphQl/Model/Resolver/Category.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category.php index 52ecdccecdc3f..6908646624e6a 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category.php @@ -112,6 +112,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $categories[$item->getId()] = $this->customAttributesFlattener ->flaternize($categories[$item->getId()]); $categories[$item->getId()]['product_count'] = $item->getProductCount(); + $categories[$item->getId()]['all_children'] = $item->getAllChildren(); } } From eebc80557f92b42d41a6a63dc01af3a29def71e5 Mon Sep 17 00:00:00 2001 From: Kieu Phan Date: Wed, 11 Apr 2018 10:42:30 -0500 Subject: [PATCH 0089/2023] MAGETWO-88232: Image from WYSIWYG do not show up on admin preview nor storefront - Build stabilization --- .../Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml | 1 - .../Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml index da81fc5f96705..4203614582711 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Cms/Test/AdminAddImageToWYSIWYGCMSPageCest.xml @@ -45,7 +45,6 @@ - diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml index 469139012cea3..28f57332650ed 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Newsletter/Test/AdminAddImageToWYSIWYGNewsletterCest.xml @@ -56,7 +56,6 @@ - From 27065cfbaeb41dd5c648125bc533082de2da6f77 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun Date: Wed, 11 Apr 2018 19:02:01 +0300 Subject: [PATCH 0090/2023] MAGETWO-89899: Proxy generator does not understand PHP 7.1 syntax --- .../SourceClassWithNamespace.php | 12 ++++++++ ...ceClassWithNamespaceInterceptor.php.sample | 28 +++++++++++++++++++ .../SourceClassWithNamespaceProxy.php.sample | 16 +++++++++++ .../Code/Generator/ClassGenerator.php | 1 + .../Code/Generator/EntityAbstract.php | 7 ++++- .../Code/Generator/Interceptor.php | 12 ++++++-- .../ObjectManager/Code/Generator/Proxy.php | 23 ++++++++++++--- 7 files changed, 91 insertions(+), 8 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest/SourceClassWithNamespace.php b/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest/SourceClassWithNamespace.php index ba7df011eec9b..481fae54e6409 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest/SourceClassWithNamespace.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest/SourceClassWithNamespace.php @@ -110,4 +110,16 @@ public static function publicChildStatic() final public function publicChildFinal() { } + + public function public71( + $arg1, + string $arg2, + ?int $arg3, + ?int $arg4 = null + ): void { + } + + public function public71Another(?\DateTime $arg1, $arg2 = null): ?string + { + } } diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceInterceptor.php.sample b/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceInterceptor.php.sample index cf8611866a885..2574c4e2a8ec9 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceInterceptor.php.sample +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceInterceptor.php.sample @@ -2,6 +2,8 @@ namespace Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace; /** + * Interceptor class for @see \Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace + * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -54,6 +56,32 @@ class Interceptor extends \Magento\Framework\Code\GeneratorTest\SourceClassWithN } } + /** + * {@inheritdoc} + */ + public function public71($arg1, string $arg2, ?int $arg3, ?int $arg4 = null) : void + { + $pluginInfo = $this->pluginList->getNext($this->subjectType, 'public71'); + if (!$pluginInfo) { + parent::public71($arg1, $arg2, $arg3, $arg4); + } else { + $this->___callPlugins('public71', func_get_args(), $pluginInfo); + } + } + + /** + * {@inheritdoc} + */ + public function public71Another(?\DateTime $arg1, $arg2 = null) : ?string + { + $pluginInfo = $this->pluginList->getNext($this->subjectType, 'public71Another'); + if (!$pluginInfo) { + return parent::public71Another($arg1, $arg2); + } else { + return $this->___callPlugins('public71Another', func_get_args(), $pluginInfo); + } + } + /** * {@inheritdoc} */ diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceProxy.php.sample b/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceProxy.php.sample index 345ac49c6a4f4..899f039511a23 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceProxy.php.sample +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceProxy.php.sample @@ -114,6 +114,22 @@ class Proxy extends \Magento\Framework\Code\GeneratorTest\SourceClassWithNamespa return $this->_getSubject()->publicChildWithoutParameters(); } + /** + * {@inheritdoc} + */ + public function public71($arg1, string $arg2, ?int $arg3, ?int $arg4 = null) : void + { + $this->_getSubject()->public71($arg1, $arg2, $arg3, $arg4); + } + + /** + * {@inheritdoc} + */ + public function public71Another(?\DateTime $arg1, $arg2 = null) : ?string + { + return $this->_getSubject()->public71Another($arg1, $arg2); + } + /** * {@inheritdoc} */ diff --git a/lib/internal/Magento/Framework/Code/Generator/ClassGenerator.php b/lib/internal/Magento/Framework/Code/Generator/ClassGenerator.php index bb1c2262132f4..0a48945e55c2d 100644 --- a/lib/internal/Magento/Framework/Code/Generator/ClassGenerator.php +++ b/lib/internal/Magento/Framework/Code/Generator/ClassGenerator.php @@ -47,6 +47,7 @@ class ClassGenerator extends \Zend\Code\Generator\ClassGenerator implements 'abstract' => 'setAbstract', 'visibility' => 'setVisibility', 'body' => 'setBody', + 'returntype' => 'setReturnType' ]; /** diff --git a/lib/internal/Magento/Framework/Code/Generator/EntityAbstract.php b/lib/internal/Magento/Framework/Code/Generator/EntityAbstract.php index d8491398a37d2..2064872b2c6a2 100644 --- a/lib/internal/Magento/Framework/Code/Generator/EntityAbstract.php +++ b/lib/internal/Magento/Framework/Code/Generator/EntityAbstract.php @@ -313,7 +313,8 @@ protected function _getMethodParameterInfo(\ReflectionParameter $parameter) $parameterInfo = [ 'name' => $parameter->getName(), 'passedByReference' => $parameter->isPassedByReference(), - 'type' => $parameter->getType(), + 'type' => $parameter->hasType() + ? $parameter->getType()->getName() : null, 'variadic' => $parameter->isVariadic() ]; @@ -336,6 +337,10 @@ protected function _getMethodParameterInfo(\ReflectionParameter $parameter) } } + if ($parameter->allowsNull() && $parameterInfo['type']) { + $parameterInfo['type'] = '?' .$parameterInfo['type']; + } + return $parameterInfo; } diff --git a/lib/internal/Magento/Framework/Interception/Code/Generator/Interceptor.php b/lib/internal/Magento/Framework/Interception/Code/Generator/Interceptor.php index 04298011e792a..9cfad52eb84e3 100644 --- a/lib/internal/Magento/Framework/Interception/Code/Generator/Interceptor.php +++ b/lib/internal/Magento/Framework/Interception/Code/Generator/Interceptor.php @@ -102,18 +102,24 @@ protected function _getMethodInfo(\ReflectionMethod $method) $parameters[] = $this->_getMethodParameterInfo($parameter); } + $returnType = $method->getReturnType(); + $returnTypeValue = $returnType + ? ($returnType->allowsNull() ? '?' : '') .$returnType->getName() + : null; $methodInfo = [ 'name' => ($method->returnsReference() ? '& ' : '') . $method->getName(), 'parameters' => $parameters, 'body' => "\$pluginInfo = \$this->pluginList->getNext(\$this->subjectType, '{$method->getName()}');\n" . "if (!\$pluginInfo) {\n" . - " return parent::{$method->getName()}({$this->_getParameterList( + " " .($returnTypeValue === 'void' ? '' : 'return') + ." parent::{$method->getName()}({$this->_getParameterList( $parameters )});\n" . "} else {\n" . - " return \$this->___callPlugins('{$method->getName()}', func_get_args(), \$pluginInfo);\n" . + " " .($returnTypeValue === 'void' ? '' : 'return') + ." \$this->___callPlugins('{$method->getName()}', func_get_args(), \$pluginInfo);\n" . "}", - 'returnType' => $method->getReturnType(), + 'returnType' => $returnTypeValue, 'docblock' => ['shortDescription' => '{@inheritdoc}'], ]; diff --git a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Proxy.php b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Proxy.php index af866478028c0..9d80e046518fd 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Proxy.php +++ b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Proxy.php @@ -159,11 +159,20 @@ protected function _getMethodInfo(\ReflectionMethod $method) $parameters[] = $this->_getMethodParameterInfo($parameter); } + $returnType = $method->getReturnType(); + $returnTypeValue = $returnType + ? ($returnType->allowsNull() ? '?' : '') .$returnType->getName() + : null; $methodInfo = [ 'name' => $method->getName(), 'parameters' => $parameters, - 'body' => $this->_getMethodBody($method->getName(), $parameterNames), + 'body' => $this->_getMethodBody( + $method->getName(), + $parameterNames, + $returnTypeValue === 'void' + ), 'docblock' => ['shortDescription' => '{@inheritdoc}'], + 'returntype' => $returnTypeValue, ]; return $methodInfo; @@ -212,16 +221,22 @@ protected function _getDefaultConstructorDefinition() * * @param string $name * @param array $parameters + * @param bool $withoutReturn * @return string */ - protected function _getMethodBody($name, array $parameters = []) - { + protected function _getMethodBody( + $name, + array $parameters = [], + bool $withoutReturn = false + ) { if (count($parameters) == 0) { $methodCall = sprintf('%s()', $name); } else { $methodCall = sprintf('%s(%s)', $name, implode(', ', $parameters)); } - return 'return $this->_getSubject()->' . $methodCall . ';'; + + return ($withoutReturn ? '' : 'return ') + .'$this->_getSubject()->' . $methodCall . ';'; } /** From bd57c88c81fc74f11943de17808bb4352cfc7e4f Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Wed, 11 Apr 2018 19:03:49 +0300 Subject: [PATCH 0091/2023] MAGETWO-89009: Split database doesn't work on 2.3-develop --- .../Magento/TestFramework/Bootstrap/SetupDocBlock.php | 2 -- .../Magento/TestFramework/Deploy/CliCommand.php | 10 +++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/dev/tests/setup-integration/framework/Magento/TestFramework/Bootstrap/SetupDocBlock.php b/dev/tests/setup-integration/framework/Magento/TestFramework/Bootstrap/SetupDocBlock.php index 8e212289eb12f..6732a8de4eb1e 100644 --- a/dev/tests/setup-integration/framework/Magento/TestFramework/Bootstrap/SetupDocBlock.php +++ b/dev/tests/setup-integration/framework/Magento/TestFramework/Bootstrap/SetupDocBlock.php @@ -5,8 +5,6 @@ */ namespace Magento\TestFramework\Bootstrap; -use Magento\TestFramework\Annotation\AppIsolation; - /** * Bootstrap of the custom DocBlock annotations. * diff --git a/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/CliCommand.php b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/CliCommand.php index a659c82d871d3..685f4df1abf2b 100644 --- a/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/CliCommand.php +++ b/dev/tests/setup-integration/framework/Magento/TestFramework/Deploy/CliCommand.php @@ -96,7 +96,7 @@ public function disableModule($moduleName) { $initParams = $this->parametersHolder->getInitParams(); $disableModuleCommand = 'php -f ' . BP . '/bin/magento module:disable '. $moduleName - . ' -vvv --magento-init-params=' . $initParams['magento-init-params']; + . ' -vvv --magento-init-params="' . $initParams['magento-init-params'] . '"'; return $this->shell->execute($disableModuleCommand); } @@ -113,8 +113,8 @@ public function splitQuote() ); $command = 'php -f ' . BP . '/bin/magento setup:db-schema:split-quote ' . implode(" ", array_keys($installParams)) . - ' -vvv --magento-init-params=' . - $initParams['magento-init-params']; + ' -vvv --magento-init-params="' . + $initParams['magento-init-params'] . '"'; $this->shell->execute($command, array_values($installParams)); } @@ -132,8 +132,8 @@ public function splitSales() ); $command = 'php -f ' . BP . '/bin/magento setup:db-schema:split-sales ' . implode(" ", array_keys($installParams)) . - ' -vvv --magento-init-params=' . - $initParams['magento-init-params']; + ' -vvv --magento-init-params="' . + $initParams['magento-init-params'] . '"'; $this->shell->execute($command, array_values($installParams)); } From 81990550a104b478d3d8cb7f1d166f828e60addd Mon Sep 17 00:00:00 2001 From: John Stennett Date: Wed, 11 Apr 2018 11:09:13 -0500 Subject: [PATCH 0092/2023] MQE-920: MSI MFTF Test Cases 2 - Adjusting "timeout" values for a few elements. --- .../FunctionalTest/Ui/Section/AdminGridControlsSection.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/Section/AdminGridControlsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/Section/AdminGridControlsSection.xml index 7adc9a193a9c6..00e5ed3308ca7 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/Section/AdminGridControlsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Ui/Section/AdminGridControlsSection.xml @@ -31,9 +31,9 @@
- + - + From d68d059a07bbaca6ea8a6163119f4f9facc49b6f Mon Sep 17 00:00:00 2001 From: Andrii Meysar Date: Wed, 11 Apr 2018 19:27:37 +0300 Subject: [PATCH 0093/2023] MAGETWO-58014: [GitHub] page cache also caches breadcrumbs #5502 --- .../Magento/Catalog/Helper/Product/View.php | 2 - .../ViewModel/Product/BreadcrumbsTest.php | 129 +++++++++ .../Catalog/ViewModel/Product/Breadcrumbs.php | 83 ++++++ .../frontend/layout/catalog_product_view.xml | 7 + .../Catalog/view/frontend/requirejs-config.js | 7 + .../templates/product/breadcrumbs.phtml | 17 ++ .../frontend/web/js/product/breadcrumbs.js | 205 ++++++++++++++ .../Theme/view/frontend/requirejs-config.js | 12 +- .../templates/page/js/require_js.phtml | 1 + .../frontend/web/js/model/breadcrumb-list.js | 10 + .../web/js/view/add-home-breadcrumb.js | 31 ++ .../view/frontend/web/js/view/breadcrumbs.js | 66 +++++ .../frontend/web/templates/breadcrumbs.html | 19 ++ .../AssertProductViewBreadcrumbsCategory.php | 73 +++++ .../Test/Page/Product/CatalogProductView.xml | 1 + .../Product/CreateSimpleProductEntityTest.xml | 14 + .../Theme/Test/Block/Html/Breadcrumbs.php | 24 ++ .../frontend/js/product/breadcrumbs.test.js | 267 ++++++++++++++++++ .../web/js/view/add-home-breadcrumb.test.js | 62 ++++ .../frontend/web/js/view/breadcrumbs.test.js | 62 ++++ 20 files changed, 1088 insertions(+), 4 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Unit/ViewModel/Product/BreadcrumbsTest.php create mode 100644 app/code/Magento/Catalog/ViewModel/Product/Breadcrumbs.php create mode 100644 app/code/Magento/Catalog/view/frontend/templates/product/breadcrumbs.phtml create mode 100644 app/code/Magento/Catalog/view/frontend/web/js/product/breadcrumbs.js create mode 100644 app/code/Magento/Theme/view/frontend/web/js/model/breadcrumb-list.js create mode 100644 app/code/Magento/Theme/view/frontend/web/js/view/add-home-breadcrumb.js create mode 100644 app/code/Magento/Theme/view/frontend/web/js/view/breadcrumbs.js create mode 100644 app/code/Magento/Theme/view/frontend/web/templates/breadcrumbs.html create mode 100644 dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductViewBreadcrumbsCategory.php create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Catalog/frontend/js/product/breadcrumbs.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/view/add-home-breadcrumb.test.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/view/breadcrumbs.test.js diff --git a/app/code/Magento/Catalog/Helper/Product/View.php b/app/code/Magento/Catalog/Helper/Product/View.php index d1e8c10ecc7fc..af062281e45fb 100644 --- a/app/code/Magento/Catalog/Helper/Product/View.php +++ b/app/code/Magento/Catalog/Helper/Product/View.php @@ -110,8 +110,6 @@ public function __construct( private function preparePageMetadata(ResultPage $resultPage, $product) { $pageLayout = $resultPage->getLayout(); - $pageLayout->createBlock(\Magento\Catalog\Block\Breadcrumbs::class); - $pageConfig = $resultPage->getConfig(); $title = $product->getMetaTitle(); diff --git a/app/code/Magento/Catalog/Test/Unit/ViewModel/Product/BreadcrumbsTest.php b/app/code/Magento/Catalog/Test/Unit/ViewModel/Product/BreadcrumbsTest.php new file mode 100644 index 0000000000000..2e5cae10563f1 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/ViewModel/Product/BreadcrumbsTest.php @@ -0,0 +1,129 @@ +catalogHelper = $this->getMockBuilder(CatalogHelper::class) + ->setMethods(['getProduct']) + ->disableOriginalConstructor() + ->getMock(); + + $this->scopeConfig = $this->getMockBuilder(ScopeConfigInterface::class) + ->setMethods(['getValue', 'isSetFlag']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->viewModel = $this->getObjectManager()->getObject( + Breadcrumbs::class, + [ + 'catalogData' => $this->catalogHelper, + 'scopeConfig' => $this->scopeConfig, + ] + ); + } + + /** + * @return void + */ + public function testGetCategoryUrlSuffix() + { + $this->scopeConfig->expects($this->once()) + ->method('getValue') + ->with('catalog/seo/category_url_suffix', \Magento\Store\Model\ScopeInterface::SCOPE_STORE) + ->willReturn('.html'); + + $this->assertEquals('.html', $this->viewModel->getCategoryUrlSuffix()); + } + + /** + * @return void + */ + public function testIsCategoryUsedInProductUrl() + { + $this->scopeConfig->expects($this->once()) + ->method('isSetFlag') + ->with('catalog/seo/product_use_categories', \Magento\Store\Model\ScopeInterface::SCOPE_STORE) + ->willReturn(false); + + $this->assertFalse($this->viewModel->isCategoryUsedInProductUrl()); + } + + /** + * @dataProvider productDataProvider + * + * @param Product|null $product + * @param string $expectedName + * @return void + */ + public function testGetProductName($product, $expectedName) + { + $this->catalogHelper->expects($this->atLeastOnce()) + ->method('getProduct') + ->willReturn($product); + + $this->assertEquals($expectedName, $this->viewModel->getProductName()); + } + + /** + * @return array + */ + public function productDataProvider() + { + return [ + [$this->getObjectManager()->getObject(Product::class, ['data' => ['name' => 'Test']]), 'Test'], + [null, ''], + ]; + } + + /** + * @return ObjectManager + */ + private function getObjectManager() + { + if (null === $this->objectManager) { + $this->objectManager = new ObjectManager($this); + } + + return $this->objectManager; + } +} diff --git a/app/code/Magento/Catalog/ViewModel/Product/Breadcrumbs.php b/app/code/Magento/Catalog/ViewModel/Product/Breadcrumbs.php new file mode 100644 index 0000000000000..4c3945569db2a --- /dev/null +++ b/app/code/Magento/Catalog/ViewModel/Product/Breadcrumbs.php @@ -0,0 +1,83 @@ +catalogData = $catalogData; + $this->scopeConfig = $scopeConfig; + } + + /** + * Returns category URL suffix. + * + * @return mixed + */ + public function getCategoryUrlSuffix() + { + return $this->scopeConfig->getValue( + 'catalog/seo/category_url_suffix', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ); + } + + /** + * Checks if categories path is used for product URLs. + * + * @return bool + */ + public function isCategoryUsedInProductUrl(): bool + { + return $this->scopeConfig->isSetFlag( + 'catalog/seo/product_use_categories', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ); + } + + /** + * Returns product name. + * + * @return string + */ + public function getProductName(): string + { + return $this->catalogData->getProduct() !== null + ? $this->catalogData->getProduct()->getName() + : ''; + } +} diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml index 1c1a919310b61..3630fddb326a7 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml @@ -28,6 +28,13 @@ itemscope itemtype="http://schema.org/Product" + + + + Magento\Catalog\ViewModel\Product\Breadcrumbs + + + diff --git a/app/code/Magento/Catalog/view/frontend/requirejs-config.js b/app/code/Magento/Catalog/view/frontend/requirejs-config.js index b588600b7db87..55df18afeb024 100644 --- a/app/code/Magento/Catalog/view/frontend/requirejs-config.js +++ b/app/code/Magento/Catalog/view/frontend/requirejs-config.js @@ -18,5 +18,12 @@ var config = { priceUtils: 'Magento_Catalog/js/price-utils', catalogAddToCart: 'Magento_Catalog/js/catalog-add-to-cart' } + }, + config: { + mixins: { + 'Magento_Theme/js/view/breadcrumbs': { + 'Magento_Catalog/js/product/breadcrumbs': true + } + } } }; diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/breadcrumbs.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/breadcrumbs.phtml new file mode 100644 index 0000000000000..a5d193afd2af4 --- /dev/null +++ b/app/code/Magento/Catalog/view/frontend/templates/product/breadcrumbs.phtml @@ -0,0 +1,17 @@ +getData('viewModel'); +?> + diff --git a/app/code/Magento/Catalog/view/frontend/web/js/product/breadcrumbs.js b/app/code/Magento/Catalog/view/frontend/web/js/product/breadcrumbs.js new file mode 100644 index 0000000000000..0072fad7e0a20 --- /dev/null +++ b/app/code/Magento/Catalog/view/frontend/web/js/product/breadcrumbs.js @@ -0,0 +1,205 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'Magento_Theme/js/model/breadcrumb-list' +], function ($, breadcrumbList) { + 'use strict'; + + return function (widget) { + + $.widget('mage.breadcrumbs', widget, { + options: { + categoryUrlSuffix: '', + useCategoryPathInUrl: false, + product: '', + menuContainer: '[data-action="navigation"] > ul' + }, + + /** @inheritdoc */ + _init: function () { + var menu, + originalInit = this._super.bind(this); + + // render breadcrumbs after navigation menu is loaded. + menu = $(this.options.menuContainer).data('mageMenu'); + + if (typeof menu === 'undefined') { + $(this.options.menuContainer).on('menucreate', function () { + originalInit(); + }); + } else { + this._super(); + } + }, + + /** @inheritdoc */ + _render: function () { + this._appendCatalogCrumbs(); + this._super(); + }, + + /** + * Append category and product crumbs. + * + * @private + */ + _appendCatalogCrumbs: function () { + var categoryCrumbs = this._resolveCategoryCrumbs(); + + categoryCrumbs.forEach(function (crumbInfo) { + breadcrumbList.push(crumbInfo); + }); + + if (this.options.product) { + breadcrumbList.push(this._getProductCrumb()); + } + }, + + /** + * Resolve categories crumbs. + * + * @return Array + * @private + */ + _resolveCategoryCrumbs: function () { + var menuItem = this._resolveCategoryMenuItem(), + categoryCrumbs = []; + + if (menuItem !== null && menuItem.length) { + categoryCrumbs.unshift(this._getCategoryCrumb(menuItem)); + + while ((menuItem = this._getParentMenuItem(menuItem)) !== null) { + categoryCrumbs.unshift(this._getCategoryCrumb(menuItem)); + } + } + + return categoryCrumbs; + }, + + /** + * Returns crumb data. + * + * @param {Object} menuItem + * @return {Object} + * @private + */ + _getCategoryCrumb: function (menuItem) { + var categoryId, + categoryName, + categoryUrl; + + categoryId = /(\d+)/i.exec(menuItem.attr('id'))[0]; + categoryName = menuItem.text(); + categoryUrl = menuItem.attr('href'); + + return { + 'name': 'category' + categoryId, + 'label': categoryName, + 'link': categoryUrl, + 'title': '' + }; + }, + + /** + * Returns product crumb. + * + * @return {Object} + * @private + */ + _getProductCrumb: function () { + return { + 'name': 'product', + 'label': this.options.product, + 'link': '', + 'title': '' + }; + }, + + /** + * Find parent menu item for current. + * + * @param {Object} menuItem + * @return {Object|null} + * @private + */ + _getParentMenuItem: function (menuItem) { + var classes, + classNav, + parentClass, + parentMenuItem = null; + + if (!menuItem) { + return null; + } + + classes = menuItem.parent().attr('class'); + classNav = classes.match(/(nav\-)[0-9]+(\-[0-9]+)+/gi); + + if (classNav) { + classNav = classNav[0]; + parentClass = classNav.substr(0, classNav.lastIndexOf('-')); + + if (parentClass.lastIndexOf('-') !== -1) { + parentMenuItem = $(this.options.menuContainer).find('.' + parentClass + ' > a'); + parentMenuItem = parentMenuItem.length ? parentMenuItem : null; + } + } + + return parentMenuItem; + }, + + /** + * Returns category menu item. + * + * Tries to resolve category from url or from referrer as fallback and + * find menu item from navigation menu by category url. + * + * @return {Object|null} + * @private + */ + _resolveCategoryMenuItem: function () { + var categoryUrl = this._resolveCategoryUrl(), + menu = $(this.options.menuContainer), + categoryMenuItem = null; + + if (categoryUrl && menu.length) { + categoryMenuItem = menu.find('a[href="' + categoryUrl + '"]'); + } + + return categoryMenuItem; + }, + + /** + * Returns category url. + * + * @return {String} + * @private + */ + _resolveCategoryUrl: function () { + var categoryUrl; + + if (this.options.useCategoryPathInUrl) { + // In case category path is used in product url - resolve category url from current url. + categoryUrl = window.location.href.split('?')[0]; + categoryUrl = categoryUrl.substring(0, categoryUrl.lastIndexOf('/')) + + this.options.categoryUrlSuffix; + } else { + // In other case - try to resolve it from referrer (without parameters). + categoryUrl = document.referrer; + + if (categoryUrl.indexOf('?') > 0) { + categoryUrl = categoryUrl.substr(0, categoryUrl.indexOf('?')); + } + } + + return categoryUrl; + } + }); + + return $.mage.breadcrumbs; + }; +}); diff --git a/app/code/Magento/Theme/view/frontend/requirejs-config.js b/app/code/Magento/Theme/view/frontend/requirejs-config.js index 51657fb11f2c8..bf38d3cbaae00 100644 --- a/app/code/Magento/Theme/view/frontend/requirejs-config.js +++ b/app/code/Magento/Theme/view/frontend/requirejs-config.js @@ -27,7 +27,8 @@ var config = { 'menu': 'mage/menu', 'popupWindow': 'mage/popup-window', 'validation': 'mage/validation/validation', - 'welcome': 'Magento_Theme/js/view/welcome' + 'welcome': 'Magento_Theme/js/view/welcome', + 'breadcrumbs': 'Magento_Theme/js/view/breadcrumbs' } }, paths: { @@ -38,5 +39,12 @@ var config = { 'mage/common', 'mage/dataPost', 'mage/bootstrap' - ] + ], + config: { + mixins: { + 'Magento_Theme/js/view/breadcrumbs': { + 'Magento_Theme/js/view/add-home-breadcrumb': true + } + } + } }; diff --git a/app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml b/app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml index 67265de90da77..2a4b07ee6396f 100644 --- a/app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/page/js/require_js.phtml @@ -5,6 +5,7 @@ */ ?> - - categoryLoader.buildHash = function(node) + diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/category-checkbox-tree.js b/app/code/Magento/Catalog/view/adminhtml/web/js/category-checkbox-tree.js new file mode 100644 index 0000000000000..215278ebae575 --- /dev/null +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/category-checkbox-tree.js @@ -0,0 +1,277 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'prototype', + 'extjs/ext-tree-checkbox', + 'mage/adminhtml/form' +], function (jQuery) { + 'use strict'; + + return function (config) { + var tree, + options = { + dataUrl: config.dataUrl, + divId: config.divId, + rootVisible: config.rootVisible, + useAjax: config.useAjax, + currentNodeId: config.currentNodeId, + jsFormObject: window[config.jsFormObject], + name: config.name, + checked: config.checked, + allowDrop: config.allowDrop, + rootId: config.rootId, + expanded: config.expanded, + categoryId: config.categoryId, + treeJson: config.treeJson + }, + data = {}, + parameters = {}, + root = {}, + len = 0, + key = '', + i = 0; + + /* eslint-disable */ + /** + * Fix ext compatibility with prototype 1.6 + */ + Ext.lib.Event.getTarget = function (e) {// eslint-disable-line no-undef + var ee = e.browserEvent || e; + + return ee.target ? Event.element(ee) : null; + }; + + /** + * @param {Object} el + * @param {Object} config + */ + Ext.tree.TreePanel.Enhanced = function (el, config) {// eslint-disable-line no-undef + Ext.tree.TreePanel.Enhanced.superclass.constructor.call(this, el, config);// eslint-disable-line no-undef + }; + + Ext.extend(Ext.tree.TreePanel.Enhanced, Ext.tree.TreePanel, {// eslint-disable-line no-undef + /* eslint-enable */ + /** + * @param {Object} config + * @param {Boolean} firstLoad + */ + loadTree: function (config, firstLoad) {// eslint-disable-line no-shadow + parameters = config.parameters, + data = config.data, + root = new Ext.tree.TreeNode(parameters);// eslint-disable-line no-undef + + if (typeof parameters.rootVisible != 'undefined') { + this.rootVisible = parameters.rootVisible * 1; + } + + this.nodeHash = {}; + this.setRootNode(root); + + if (firstLoad) { + this.addListener('click', this.categoryClick.createDelegate(this)); + } + + this.loader.buildCategoryTree(root, data); + this.el.dom.innerHTML = ''; + // render the tree + this.render(); + }, + + /** + * @param {Object} node + */ + categoryClick: function (node) { + node.getUI().check(!node.getUI().checked()); + } + }); + + jQuery(function () { + var categoryLoader = new Ext.tree.TreeLoader({// eslint-disable-line no-undef + dataUrl: config.dataUrl + }); + + /** + * @param {Object} response + * @param {Object} parent + * @param {Function} callback + */ + categoryLoader.processResponse = function (response, parent, callback) { + config = JSON.parse(response.responseText); + + this.buildCategoryTree(parent, config); + + if (typeof callback === 'function') { + callback(this, parent); + } + }; + + /** + * @param {Object} config + * @returns {Object} + */ + categoryLoader.createNode = function (config) {// eslint-disable-line no-shadow + var node; + + config.uiProvider = Ext.tree.CheckboxNodeUI;// eslint-disable-line no-undef + + if (config.children && !config.children.length) { + delete config.children; + node = new Ext.tree.AsyncTreeNode(config);// eslint-disable-line no-undef + } else { + node = new Ext.tree.TreeNode(config);// eslint-disable-line no-undef + } + + return node; + }; + + /** + * @param {Object} parent + * @param {Object} config + * @param {Integer} i + */ + categoryLoader.processCategoryTree = function (parent, config, i) {// eslint-disable-line no-shadow + var node, + _node = {}; + + config[i].uiProvider = Ext.tree.CheckboxNodeUI;// eslint-disable-line no-undef + + _node = Object.clone(config[i]); + + if (_node.children && !_node.children.length) { + delete _node.children; + node = new Ext.tree.AsyncTreeNode(_node);// eslint-disable-line no-undef + } else { + node = new Ext.tree.TreeNode(config[i]);// eslint-disable-line no-undef + } + parent.appendChild(node); + node.loader = node.getOwnerTree().loader; + + if (_node.children) { + categoryLoader.buildCategoryTree(node, _node.children); + } + }; + + /** + * @param {Object} parent + * @param {Object} config + * @returns {void} + */ + categoryLoader.buildCategoryTree = function (parent, config) {// eslint-disable-line no-shadow + var i = 0; + if (!config) { + return null; + } + + if (parent && config && config.length) { + for (i = 0; i < config.length; i++) { + categoryLoader.processCategoryTree(parent, config, i); + } + } + }; + + /** + * + * @param {Object} hash + * @param {Object} node + * @returns {Object} + */ + categoryLoader.buildHashChildren = function (hash, node) {// eslint-disable-line no-shadow + var i = 0; + // eslint-disable-next-line no-extra-parens + if ((node.childNodes.length > 0) || (node.loaded === false && node.loading === false)) { + hash.children = []; + + for (i = 0, len = node.childNodes.length; i < len; i++) { + /* eslint-disable */ + if (!hash.children) { + hash.children = []; + } + /* eslint-enable */ + hash.children.push(this.buildHash(node.childNodes[i])); + } + } + + return hash; + }; + + /** + * @param {Object} node + * @returns {Object} + */ + categoryLoader.buildHash = function (node) { + var hash = {}; + + hash = this.toArray(node.attributes); + + return categoryLoader.buildHashChildren(hash, node); + }; + + /** + * @param {Object} attributes + * @returns {Object} + */ + categoryLoader.toArray = function (attributes) { + data = {}; + + for (key in attributes) { + + if (attributes[key]) { + data[key] = attributes[key]; + } + } + + return data; + }; + + categoryLoader.on('beforeload', function (treeLoader, node) { + treeLoader.baseParams.id = node.attributes.id; + }); + + /* eslint-disable */ + categoryLoader.on('load', function () { + varienWindowOnload(); + }); + + tree = new Ext.tree.TreePanel.Enhanced(options.divId, { + animate: false, + loader: categoryLoader, + enableDD: false, + containerScroll: true, + selModel: new Ext.tree.CheckNodeMultiSelectionModel(), + rootVisible: options.rootVisible, + useAjax: options.useAjax, + currentNodeId: options.currentNodeId, + addNodeTo: false, + rootUIProvider: Ext.tree.CheckboxNodeUI + }); + + tree.on('check', function (node) { + options.jsFormObject.updateElement.value = this.getChecked().join(', '); + varienElementMethods.setHasChanges(node.getUI().checkbox); + }, tree); + + // set the root node + //jscs:disable requireCamelCaseOrUpperCaseIdentifiers + parameters = { + text: options.name, + draggable: false, + checked: options.checked, + uiProvider: Ext.tree.CheckboxNodeUI, + allowDrop: options.allowDrop, + id: options.rootId, + expanded: options.expanded, + category_id: options.categoryId + }; + //jscs:enable requireCamelCaseOrUpperCaseIdentifiers + + tree.loadTree({ + parameters: parameters, data: options.treeJson + }, true); + /* eslint-enable */ + }); + }; +}); diff --git a/app/code/Magento/Rule/view/adminhtml/web/rules.js b/app/code/Magento/Rule/view/adminhtml/web/rules.js index 5c4be367b9cb3..b094b9818364a 100644 --- a/app/code/Magento/Rule/view/adminhtml/web/rules.js +++ b/app/code/Magento/Rule/view/adminhtml/web/rules.js @@ -137,7 +137,7 @@ define([ }, onSuccess: function (transport) { if (this._processSuccess(transport)) { - $(chooser).update(transport.responseText); + jQuery(chooser).html(transport.responseText); this.showChooserLoaded(chooser, transport); jQuery(chooser).trigger('contentUpdated'); } diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Widget/CategoriesJson.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Widget/CategoriesJson.php new file mode 100644 index 0000000000000..f413a7d047d62 --- /dev/null +++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Widget/CategoriesJson.php @@ -0,0 +1,26 @@ + + + +
+ + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/PriceRuleConditionsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/PriceRuleConditionsSection.xml new file mode 100644 index 0000000000000..39c6dd6b31968 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/PriceRuleConditionsSection.xml @@ -0,0 +1,20 @@ + + +
+ + + + + + + + + + +
+
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/PriceRuleCategoryNestingTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/PriceRuleCategoryNestingTest.xml new file mode 100644 index 0000000000000..9d47a5e823e83 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/PriceRuleCategoryNestingTest.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4ee218691e762465c9a8abc27193731a357c4b01 Mon Sep 17 00:00:00 2001 From: Valerij Ivashchenko Date: Fri, 4 May 2018 22:07:18 +0300 Subject: [PATCH 0487/2023] small optimisation in if-condition --- .../Adminhtml/Product/Initialization/Helper/AttributeFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index 237168282afae..4641e4fdd7f95 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -31,7 +31,7 @@ public function prepareProductAttributes(Product $product, array $productData, a $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === "1"; if ($value === '' && $considerUseDefaultsAttribute) { /** @var $product Product */ - if ((bool)$product->getData($attribute) === (bool)$value) { + if ((bool)$product->getData($attribute) === false) { unset($productData[$attribute]); } } From 1fce0a5eacc884adc53a7791fa0f63af9d7d7b2b Mon Sep 17 00:00:00 2001 From: Valerij Ivashchenko Date: Sun, 6 May 2018 00:10:09 +0300 Subject: [PATCH 0488/2023] optimize 2 nested if to one --- .../Product/Initialization/Helper/AttributeFilter.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index 4641e4fdd7f95..0c13dd486e325 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -29,11 +29,8 @@ public function prepareProductAttributes(Product $product, array $productData, a { foreach ($productData as $attribute => $value) { $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === "1"; - if ($value === '' && $considerUseDefaultsAttribute) { - /** @var $product Product */ - if ((bool)$product->getData($attribute) === false) { - unset($productData[$attribute]); - } + if ($value === '' && $considerUseDefaultsAttribute && !$product->getData($attribute)) { + unset($productData[$attribute]); } } return $productData; From b77ff138442d029e53f15c87d3a91a2676e1e4d2 Mon Sep 17 00:00:00 2001 From: Valerij Ivashchenko Date: Sun, 6 May 2018 00:24:21 +0300 Subject: [PATCH 0489/2023] change attributeShouldNotBeUpdated() visibility to protected --- .../Initialization/Helper/AttributeFilter.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index 0c13dd486e325..4b503721f9400 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -28,11 +28,24 @@ class AttributeFilter public function prepareProductAttributes(Product $product, array $productData, array $useDefaults) { foreach ($productData as $attribute => $value) { - $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === "1"; - if ($value === '' && $considerUseDefaultsAttribute && !$product->getData($attribute)) { + if ($this->attributeShouldNotBeUpdated($product, $useDefaults, $attribute, $value)) { unset($productData[$attribute]); } } return $productData; } + + /** + * @param $product + * @param $useDefaults + * @param $attribute + * @param $value + * @return bool + */ + protected function attributeShouldNotBeUpdated(Product $product, $useDefaults, $attribute, $value) + { + $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === "1"; + + return ($value === '' && $considerUseDefaultsAttribute && !$product->getData($attribute)); + } } From 163c9da1ea464865a66be38fe82522c4337b1243 Mon Sep 17 00:00:00 2001 From: Valerij Ivashchenko Date: Sun, 6 May 2018 00:28:25 +0300 Subject: [PATCH 0490/2023] replace tabs by spaces --- .../Initialization/Helper/AttributeFilter.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index 4b503721f9400..52752a53e9646 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -35,17 +35,17 @@ public function prepareProductAttributes(Product $product, array $productData, a return $productData; } - /** - * @param $product - * @param $useDefaults - * @param $attribute - * @param $value - * @return bool - */ + /** + * @param $product + * @param $useDefaults + * @param $attribute + * @param $value + * @return bool + */ protected function attributeShouldNotBeUpdated(Product $product, $useDefaults, $attribute, $value) { - $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === "1"; + $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === "1"; - return ($value === '' && $considerUseDefaultsAttribute && !$product->getData($attribute)); + return ($value === '' && $considerUseDefaultsAttribute && !$product->getData($attribute)); } } From 75deab25fb1f95608e516f2c28e06f0976a632cc Mon Sep 17 00:00:00 2001 From: Valerij Ivashchenko Date: Sun, 6 May 2018 00:30:34 +0300 Subject: [PATCH 0491/2023] add blank row before return statement --- .../Adminhtml/Product/Initialization/Helper/AttributeFilter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index 52752a53e9646..f084a6dfad68a 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -32,6 +32,7 @@ public function prepareProductAttributes(Product $product, array $productData, a unset($productData[$attribute]); } } + return $productData; } From b4ec36dd05501f70ca698d52cd320c26412489d3 Mon Sep 17 00:00:00 2001 From: Valerij Ivashchenko Date: Sun, 6 May 2018 17:18:36 +0300 Subject: [PATCH 0492/2023] rename attributeShouldNotBeUpdated() to isAttributeShouldNotBeUpdated() --- .../Product/Initialization/Helper/AttributeFilter.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index f084a6dfad68a..1ab952a460cd3 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -28,22 +28,22 @@ class AttributeFilter public function prepareProductAttributes(Product $product, array $productData, array $useDefaults) { foreach ($productData as $attribute => $value) { - if ($this->attributeShouldNotBeUpdated($product, $useDefaults, $attribute, $value)) { + if ($this->isAttributeShouldNotBeUpdated($product, $useDefaults, $attribute, $value)) { unset($productData[$attribute]); } } - + return $productData; } /** - * @param $product + * @param Product $product * @param $useDefaults * @param $attribute * @param $value * @return bool */ - protected function attributeShouldNotBeUpdated(Product $product, $useDefaults, $attribute, $value) + private function isAttributeShouldNotBeUpdated(Product $product, $useDefaults, $attribute, $value) { $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === "1"; From 435d241cbf5552cbae2dc6029e9442cc4e1d5f9f Mon Sep 17 00:00:00 2001 From: Daniel Ruf Date: Sat, 5 May 2018 22:11:25 +0200 Subject: [PATCH 0493/2023] chore: use random_int() in some places --- .../Backend/Block/Widget/Grid/Column/Renderer/Massaction.php | 2 +- .../Catalog/Model/Indexer/Category/Product/AbstractAction.php | 2 +- app/code/Magento/SalesRule/Model/Coupon/Codegenerator.php | 4 ++-- app/code/Magento/SalesRule/Model/Rule.php | 2 +- lib/internal/Magento/Framework/Encryption/Crypt.php | 2 +- .../Magento/Framework/Setup/BackendFrontnameGenerator.php | 2 +- lib/internal/Magento/Framework/Webapi/ErrorProcessor.php | 2 +- pub/errors/processor.php | 2 +- .../src/Magento/Setup/Model/Address/AddressDataGenerator.php | 2 +- setup/src/Magento/Setup/Model/DataGenerator.php | 4 ++-- .../Magento/Setup/Model/Description/DescriptionGenerator.php | 2 +- .../Setup/Model/Description/DescriptionParagraphGenerator.php | 2 +- .../Setup/Model/Description/DescriptionSentenceGenerator.php | 2 +- setup/src/Magento/Setup/Model/Description/Mixin/BoldMixin.php | 2 +- .../Model/Description/Mixin/Helper/RandomWordSelector.php | 2 +- .../src/Magento/Setup/Model/Description/Mixin/ItalicMixin.php | 2 +- setup/src/Magento/Setup/Model/Description/Mixin/SpanMixin.php | 2 +- setup/src/Magento/Setup/Model/Dictionary.php | 2 +- 18 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Massaction.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Massaction.php index 320713f8b57c4..a611e91f32f00 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Massaction.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Massaction.php @@ -65,7 +65,7 @@ public function render(\Magento\Framework\DataObject $row) */ protected function _getCheckboxHtml($value, $checked) { - $id = 'id_' . rand(0, 999); + $id = 'id_' . random_int(0, 999); $html = '
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/ActionGroup/StorefrontSalesRuleActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/ActionGroup/StorefrontSalesRuleActionGroup.xml index 65b40abb72fd8..bba7a81a7c884 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/ActionGroup/StorefrontSalesRuleActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/ActionGroup/StorefrontSalesRuleActionGroup.xml @@ -38,4 +38,20 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateBuyXGetYFreeTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateBuyXGetYFreeTest.xml index 72ea11385e1ea..e8b1ebfa99be0 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateBuyXGetYFreeTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateBuyXGetYFreeTest.xml @@ -54,13 +54,10 @@ - - - - - - - - + + + + + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml index 805783f6e922f..33703d3a97072 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml @@ -20,6 +20,7 @@ + @@ -28,7 +29,7 @@ - + @@ -62,5 +63,24 @@ + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateFixedAmountDiscountTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateFixedAmountDiscountTest.xml index 3457f780244ec..b9fbf38236c11 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateFixedAmountDiscountTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateFixedAmountDiscountTest.xml @@ -53,12 +53,10 @@ - - - - - - - + + + + + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateFixedAmountWholeCartDiscountTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateFixedAmountWholeCartDiscountTest.xml index 2d2bb24868032..6c6a1ece40444 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateFixedAmountWholeCartDiscountTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateFixedAmountWholeCartDiscountTest.xml @@ -53,14 +53,10 @@ - - - - - - - - - + + + + + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreatePercentOfProductPriceTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreatePercentOfProductPriceTest.xml index 6587044ea4e44..3086a7855d647 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreatePercentOfProductPriceTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreatePercentOfProductPriceTest.xml @@ -53,12 +53,10 @@ - - - - - - - + + + + + From c9207b63d2ce997002c2e66c5156d05bdbbeb376 Mon Sep 17 00:00:00 2001 From: Dan Mooney Date: Fri, 25 May 2018 13:08:03 -0500 Subject: [PATCH 0811/2023] MAGETWO-90347: Close Icon displays for attribute set on catalog product edit form Set isRemoveSelectedIcon to false by default in ui-select, and set it to true in url inputs --- app/code/Magento/Catalog/Ui/Component/UrlInput/Category.php | 1 + app/code/Magento/Catalog/Ui/Component/UrlInput/Product.php | 1 + app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Ui/Component/UrlInput/Category.php b/app/code/Magento/Catalog/Ui/Component/UrlInput/Category.php index 836bc5058777d..01d93de577927 100644 --- a/app/code/Magento/Catalog/Ui/Component/UrlInput/Category.php +++ b/app/code/Magento/Catalog/Ui/Component/UrlInput/Category.php @@ -46,6 +46,7 @@ public function getConfig(): array 'sortOrder' => 30, 'missingValuePlaceholder' => __('Category with ID: %s doesn\'t exist'), 'isDisplayMissingValuePlaceholder' => true, + 'isRemoveSelectedIcon' => true, ]; } } diff --git a/app/code/Magento/Catalog/Ui/Component/UrlInput/Product.php b/app/code/Magento/Catalog/Ui/Component/UrlInput/Product.php index efa8417e4686a..be73940237db4 100644 --- a/app/code/Magento/Catalog/Ui/Component/UrlInput/Product.php +++ b/app/code/Magento/Catalog/Ui/Component/UrlInput/Product.php @@ -50,6 +50,7 @@ public function getConfig(): array 'emptyOptionsHtml' => __('Start typing to find products'), 'missingValuePlaceholder' => __('Product with ID: %s doesn\'t exist'), 'isDisplayMissingValuePlaceholder' => true, + 'isRemoveSelectedIcon' => true, 'validationUrl' => $this->urlBuilder->getUrl('catalog/product/getSelected'), ]; } diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js index 5ed9199604c25..dba0992c5ba52 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js @@ -176,7 +176,7 @@ define([ pageLimit: 50, deviation: 30, validationLoading: false, - isRemoveSelectedIcon: true, + isRemoveSelectedIcon: false, debounce: 300, missingValuePlaceholder: $t('Entity with ID: %s doesn\'t exist'), isDisplayMissingValuePlaceholder: false, From d77efd801835300a0576276c450453a6d66d13e6 Mon Sep 17 00:00:00 2001 From: Max Lesechko Date: Fri, 25 May 2018 13:31:56 -0500 Subject: [PATCH 0812/2023] MAGETWO-88814: [Performance] Some indexes become recreated on db with prefixes --- .../Setup/Declaration/WhitelistDeclarationTest.php | 10 +++++++++- .../Setup/Declaration/_files/ignore_whitelisting.json | 1 - .../Declaration/_files/ignore_whitelisting/ce.json | 7 +++++++ 3 files changed, 16 insertions(+), 2 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/Setup/Declaration/_files/ignore_whitelisting.json create mode 100644 dev/tests/integration/testsuite/Magento/Setup/Declaration/_files/ignore_whitelisting/ce.json diff --git a/dev/tests/integration/testsuite/Magento/Setup/Declaration/WhitelistDeclarationTest.php b/dev/tests/integration/testsuite/Magento/Setup/Declaration/WhitelistDeclarationTest.php index 5e0df204957a7..203f63a92da52 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Declaration/WhitelistDeclarationTest.php +++ b/dev/tests/integration/testsuite/Magento/Setup/Declaration/WhitelistDeclarationTest.php @@ -7,6 +7,7 @@ namespace Magento\Setup\Declaration; +use Magento\Framework\App\Utility\Files; use Magento\Framework\Component\ComponentRegistrar; use Magento\Framework\Component\ComponentRegistrarInterface; use Magento\Framework\Setup\Declaration\Schema\Dto\Constraint; @@ -86,7 +87,14 @@ public function testConstraintsAndIndexesAreWhitelisted() */ private function filterUndeclaredElements(array $undeclaredElements): array { - $ignoredElements = json_decode(file_get_contents(__DIR__ . '/_files/ignore_whitelisting.json'), true); + $files = Files::getFiles([__DIR__ . '/_files/ignore_whitelisting'], '*.json'); + $ignoredElements = []; + foreach ($files as $filePath) { + $ignoredElements = array_merge_recursive( + $ignoredElements, + json_decode(file_get_contents($filePath), true) + ); + } return $this->arrayRecursiveDiff($undeclaredElements, $ignoredElements); } diff --git a/dev/tests/integration/testsuite/Magento/Setup/Declaration/_files/ignore_whitelisting.json b/dev/tests/integration/testsuite/Magento/Setup/Declaration/_files/ignore_whitelisting.json deleted file mode 100644 index 0967ef424bce6..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Setup/Declaration/_files/ignore_whitelisting.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/dev/tests/integration/testsuite/Magento/Setup/Declaration/_files/ignore_whitelisting/ce.json b/dev/tests/integration/testsuite/Magento/Setup/Declaration/_files/ignore_whitelisting/ce.json new file mode 100644 index 0000000000000..881481ab407bc --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Setup/Declaration/_files/ignore_whitelisting/ce.json @@ -0,0 +1,7 @@ +{ + "patch_list": { + "constraint": [ + "PRIMARY" + ] + } +} From 7fe4eaec58676ae3119b1b5fe5a2d66dc48da96d Mon Sep 17 00:00:00 2001 From: Ji Lu Date: Fri, 25 May 2018 14:05:08 -0500 Subject: [PATCH 0813/2023] MC-188: Admin should be able to add images for category MC-212: Admin should be able to remove images from category - added mftf tests --- .../Backend/ActionGroup/LogoutActionGroup.xml | 2 +- .../Backend/Page/AdminLogoutPage.xml | 4 +- .../ActionGroup/AdminCategoryActionGroup.xml | 64 +++++++++++++++++++ .../Catalog/Page/AdminCategoryPage.xml | 1 + .../Section/AdminCategoryContentSection.xml | 19 ++++++ .../Section/StorefrontCategoryMainSection.xml | 1 + .../Test/AdminAddImageForCategoryTest.xml | 48 ++++++++++++++ ...minRemoveDefaultImageSimpleProductTest.xml | 1 - .../Test/AdminRemoveImageFromCategoryTest.xml | 51 +++++++++++++++ 9 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminCategoryContentSection.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageForCategoryTest.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminRemoveImageFromCategoryTest.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Backend/ActionGroup/LogoutActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Backend/ActionGroup/LogoutActionGroup.xml index 1e7914c32c939..4a5bed2ed0a68 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Backend/ActionGroup/LogoutActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Backend/ActionGroup/LogoutActionGroup.xml @@ -9,6 +9,6 @@ - + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Backend/Page/AdminLogoutPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Backend/Page/AdminLogoutPage.xml index 5660df619c73d..6eb02dfb3b7fb 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Backend/Page/AdminLogoutPage.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Backend/Page/AdminLogoutPage.xml @@ -8,7 +8,5 @@ - -
- + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml index 19c9ca94377f2..96e40e348a6f2 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml @@ -25,6 +25,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Page/AdminCategoryPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Page/AdminCategoryPage.xml index f51d2e8a28939..7d0e7f4f99e42 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Page/AdminCategoryPage.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Page/AdminCategoryPage.xml @@ -18,5 +18,6 @@
+
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminCategoryContentSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminCategoryContentSection.xml new file mode 100644 index 0000000000000..d0e129e1bb441 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminCategoryContentSection.xml @@ -0,0 +1,19 @@ + + + + +
+ + + + + + +
+
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontCategoryMainSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontCategoryMainSection.xml index 39275d61485a8..45a85386fe726 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontCategoryMainSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontCategoryMainSection.xml @@ -23,5 +23,6 @@ +
diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageForCategoryTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageForCategoryTest.xml new file mode 100644 index 0000000000000..ba90296d12380 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminAddImageForCategoryTest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + <description value="Admin should be able to add image to a Category"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-188"/> + <group value="Catalog"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="DeleteCategory" stepKey="DeleteCategory"> + <argument name="categoryEntity" value="SimpleSubCategory"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Go to create a new category with image --> + <actionGroup ref="goToCreateCategoryPage" stepKey="goToCreateCategoryPage"/> + <actionGroup ref="fillCategoryForm" stepKey="fillCategoryForm"> + <argument name="categoryEntity" value="SimpleSubCategory"/> + </actionGroup> + <actionGroup ref="addCategoryImage" stepKey="addCategoryImage"/> + <actionGroup ref="saveCategoryForm" stepKey="saveCategoryForm"/> + + <!-- Verify category with image in admin --> + <actionGroup ref="checkCategoryImageInAdmin" stepKey="checkCategoryImageInAdmin"/> + + <!-- Verify category with image in storefront --> + <actionGroup ref="CheckCategoryOnStorefront" stepKey="CheckCategoryOnStorefront"> + <argument name="categoryEntity" value="SimpleSubCategory"/> + </actionGroup> + <seeElement selector="{{StorefrontCategoryMainSection.imageSource(ImageUpload.filename)}}" stepKey="seeImage"/> + </test> +</tests> \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminRemoveDefaultImageSimpleProductTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminRemoveDefaultImageSimpleProductTest.xml index 36b2c5e9ffac5..4623f2ad4a90c 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminRemoveDefaultImageSimpleProductTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminRemoveDefaultImageSimpleProductTest.xml @@ -17,7 +17,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-195"/> <group value="Catalog"/> - <group value="ji"/> </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminRemoveImageFromCategoryTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminRemoveImageFromCategoryTest.xml new file mode 100644 index 0000000000000..11b29b9dd33e7 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminRemoveImageFromCategoryTest.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdminRemoveImageFromCategoryTest"> + <annotations> + <features value="Catalog"/> + <stories value="Add/remove images and videos for all product types and category"/> + <title value="Admin should be able to remove image from a Category"/> + <description value="Admin should be able to remove image from a Category"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-212"/> + <group value="Catalog"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="DeleteCategory" stepKey="DeleteCategory"> + <argument name="categoryEntity" value="SimpleSubCategory"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Go to create a new category with image --> + <actionGroup ref="goToCreateCategoryPage" stepKey="goToCreateCategoryPage"/> + <actionGroup ref="fillCategoryForm" stepKey="fillCategoryForm"> + <argument name="categoryEntity" value="SimpleSubCategory"/> + </actionGroup> + <actionGroup ref="addCategoryImage" stepKey="addCategoryImage"/> + <actionGroup ref="saveCategoryForm" stepKey="saveCategoryForm"/> + <actionGroup ref="checkCategoryImageInAdmin" stepKey="checkCategoryImageInAdmin"/> + + <!-- Remove image from category --> + <actionGroup ref="removeCategoryImage" stepKey="removeCategoryImage"/> + <actionGroup ref="saveCategoryForm" stepKey="saveCategoryFormAfterRemove"/> + + <actionGroup ref="CheckCategoryOnStorefront" stepKey="CheckCategoryOnStorefront"> + <argument name="categoryEntity" value="SimpleSubCategory"/> + </actionGroup> + + <!-- Verify category with no image in storefront --> + <dontSee selector="{{StorefrontCategoryMainSection.categoryImage}}" stepKey="dontSeeImage"/> + </test> +</tests> \ No newline at end of file From 8b02118b7af1c8edcae46b59fa556406ff53351e Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@magento.com> Date: Fri, 25 May 2018 14:59:23 -0500 Subject: [PATCH 0814/2023] MC-75: Admin should be able to create a cart price rule for auto generated coupon codes --- .../AdminCartPriceRulesFormSection.xml | 9 +++ ...ateCartPriceRuleForGeneratedCouponTest.xml | 79 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/AdminCartPriceRulesFormSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/AdminCartPriceRulesFormSection.xml index d95cdee4ef4c8..3912a6ab31e8d 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/AdminCartPriceRulesFormSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/AdminCartPriceRulesFormSection.xml @@ -9,6 +9,7 @@ xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> <section name="AdminCartPriceRulesFormSection"> <element name="save" type="button" selector="#save" timeout="30"/> + <element name="saveAndContinue" type="button" selector="#save_and_continue" timeout="30"/> <element name="delete" type="button" selector="#delete" timeout="30"/> <element name="modalAcceptButton" type="button" selector="button.action-accept" timeout="30"/> @@ -19,11 +20,19 @@ <element name="customerGroups" type="multiselect" selector="select[name='customer_group_ids']"/> <element name="coupon" type="select" selector="select[name='coupon_type']"/> <element name="couponCode" type="input" selector="input[name='coupon_code']"/> + <element name="useAutoGeneration" type="checkbox" selector="input[name='use_auto_generation']"/> <!-- Actions sub-form --> <element name="actionsHeader" type="button" selector="div[data-index='actions']" timeout="30"/> <element name="apply" type="select" selector="select[name='simple_action']"/> <element name="discountAmount" type="input" selector="input[name='discount_amount']"/> <element name="discountStep" type="input" selector="input[name='discount_step']"/> + + <!-- Manage Coupon Codes sub-form --> + <element name="manageCouponCodesHeader" type="button" selector="div[data-index='manage_coupon_codes']" timeout="30"/> + <element name="successMessage" type="text" selector="div.message.message-success.success"/> + <element name="couponQty" type="input" selector="#coupons_qty"/> + <element name="generateCouponsButton" type="button" selector="#coupons_generate_button" timeout="30"/> + <element name="generatedCouponByIndex" type="text" selector="#couponCodesGrid_table > tbody > tr:nth-child({{var}}) > td.col-code" parameterized="true"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml new file mode 100644 index 0000000000000..b5b30ce3c265a --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdminCreateCartPriceRuleForGeneratedCouponTest"> + <annotations> + <features value="SalesRule"/> + <stories value="Create cart price rule"/> + <title value="Admin should be able to create a cart price rule for auto generated coupon codes"/> + <description value="Admin should be able to create a cart price rule for auto generated coupon codes"/> + <severity value="AVERAGE"/> + <testCaseId value="MC-75"/> + <group value="SalesRule"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + + <after> + <!-- Delete the cart price rule we made during the test --> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> + <argument name="ruleName" value="{{_defaultCoupon.code}}"/> + </actionGroup> + <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + </after> + + <!-- Create a cart price rule --> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForPriceList"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{_defaultCoupon.code}}" stepKey="fillRuleName"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Main Website" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="NOT LOGGED IN" stepKey="selectCustomerGroup"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="Specific Coupon" stepKey="selectCouponType"/> + <checkOption selector="{{AdminCartPriceRulesFormSection.useAutoGeneration}}" stepKey="tickAutoGeneration"/> + <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="Fixed amount discount for whole cart" stepKey="selectActionType"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="0.99" stepKey="fillDiscountAmount"/> + <click selector="{{AdminCartPriceRulesFormSection.saveAndContinue}}" stepKey="clickSaveAndContinueButton"/> + + <!-- Generate some coupon codes --> + <click selector="{{AdminCartPriceRulesFormSection.manageCouponCodesHeader}}" stepKey="expandCouponSection"/> + <fillField selector="{{AdminCartPriceRulesFormSection.couponQty}}" userInput="10" stepKey="fillCouponQty"/> + <click selector="{{AdminCartPriceRulesFormSection.generateCouponsButton}}" stepKey="clickGenerate"/> + <see selector="{{AdminCartPriceRulesFormSection.successMessage}}" userInput="10 coupon(s) have been generated." stepKey="seeGenerationSuccess"/> + + <!-- Grab a coupon code and hold on to it for later --> + <grabTextFrom selector="{{AdminCartPriceRulesFormSection.generatedCouponByIndex('1')}}" stepKey="grabCouponCode"/> + + <!-- Create a product to check the storefront --> + <actionGroup ref="FillAdminSimpleProductForm" stepKey="fillProductFieldsInAdmin"> + <argument name="category" value="$$createPreReqCategory$$"/> + <argument name="simpleProduct" value="_defaultProduct"/> + </actionGroup> + + <!-- Spot check the storefront --> + <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> + <waitForPageLoad stepKey="waitForCartPage"/> + <conditionalClick selector="{{StorefrontSalesRuleCartCouponSection.couponHeader}}" dependentSelector="{{StorefrontSalesRuleCartCouponSection.discountBlockActive}}" visible="false" stepKey="clickCouponHeader"/> + <waitForElementVisible selector="{{StorefrontSalesRuleCartCouponSection.couponField}}" stepKey="waitForCouponField" /> + <fillField selector="{{StorefrontSalesRuleCartCouponSection.couponField}}" userInput="{$grabCouponCode}" stepKey="fillCouponField"/> + <click selector="{{StorefrontSalesRuleCartCouponSection.applyButton}}" stepKey="clickApplyButton"/> + <waitForPageLoad stepKey="waitForProductPageLoad2"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$0.99" stepKey="seeDiscountTotal"/> + </test> +</tests> From f36db11b7ebe50f91dcef2de2c562dd04fad5a15 Mon Sep 17 00:00:00 2001 From: Tommy Wiebell <twiebell@magento.com> Date: Fri, 25 May 2018 16:06:07 -0500 Subject: [PATCH 0815/2023] MAGETWO-92219: Incorrect types of extensions for attributes - Move attribute type fix from Catalog to abstract attribute implementation --- .../Model/ResourceModel/Eav/Attribute.php | 14 -------------- .../Entity/Attribute/AbstractAttribute.php | 19 +++++++++++++++++-- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index d882ad078b97f..8f8e9f6bfedfa 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -895,18 +895,4 @@ public function setIsFilterableInGrid($isFilterableInGrid) $this->setData(self::IS_FILTERABLE_IN_GRID, $isFilterableInGrid); return $this; } - - /** - * @return \Magento\Eav\Api\Data\AttributeExtensionInterface - */ - public function getExtensionAttributes() - { - $extensionAttributes = $this->_getExtensionAttributes(); - if (null === $extensionAttributes) { - /** @var \Magento\Eav\Api\Data\AttributeExtensionInterface $extensionAttributes */ - $extensionAttributes = $this->eavAttributeFactory->create(); - $this->setExtensionAttributes($extensionAttributes); - } - return $extensionAttributes; - } } diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index a7170888f8a01..f5c7d88919f3c 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -141,6 +141,11 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens 'static', ]; + /** + * @var \Magento\Eav\Api\Data\AttributeExtensionFactory + */ + private $eavExtensionFactory; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -157,6 +162,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data + * @param \Magento\Eav\Api\Data\AttributeExtensionFactory|null $eavExtensionFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @codeCoverageIgnore */ @@ -175,7 +181,8 @@ public function __construct( \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + \Magento\Eav\Api\Data\AttributeExtensionFactory $eavExtensionFactory = null ) { parent::__construct( $context, @@ -194,6 +201,8 @@ public function __construct( $this->optionDataFactory = $optionDataFactory; $this->dataObjectProcessor = $dataObjectProcessor; $this->dataObjectHelper = $dataObjectHelper; + $this->eavExtensionFactory = $eavExtensionFactory ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Eav\Api\Data\AttributeExtensionFactory::class); } /** @@ -1314,7 +1323,13 @@ public function setValidationRules(array $validationRules = null) */ public function getExtensionAttributes() { - return $this->_getExtensionAttributes(); + $extensionAttributes = $this->_getExtensionAttributes(); + if (!($extensionAttributes instanceof \Magento\Eav\Api\Data\AttributeExtensionInterface)) { + /** @var \Magento\Eav\Api\Data\AttributeExtensionInterface $extensionAttributes */ + $extensionAttributes = $this->eavExtensionFactory->create(); + $this->setExtensionAttributes($extensionAttributes); + } + return $extensionAttributes; } /** From d8a6082e2bb0045dc8b2aa221b4b1d76168c4921 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Sat, 26 May 2018 00:03:23 -0500 Subject: [PATCH 0816/2023] MAGETWO-88814: [Performance] Some indexes become recreated on db with prefixes --- .../Declaration/WhitelistDeclarationTest.php | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Setup/Declaration/WhitelistDeclarationTest.php b/dev/tests/integration/testsuite/Magento/Setup/Declaration/WhitelistDeclarationTest.php index 203f63a92da52..6b92e687284db 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Declaration/WhitelistDeclarationTest.php +++ b/dev/tests/integration/testsuite/Magento/Setup/Declaration/WhitelistDeclarationTest.php @@ -7,14 +7,16 @@ namespace Magento\Setup\Declaration; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\App\Utility\Files; use Magento\Framework\Component\ComponentRegistrar; use Magento\Framework\Component\ComponentRegistrarInterface; +use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Setup\Declaration\Schema\Dto\Constraint; use Magento\Framework\Setup\Declaration\Schema\Dto\Index; -use Magento\Framework\Setup\Declaration\Schema\Dto\Schema; use Magento\Framework\Setup\Declaration\Schema\SchemaConfigInterface; use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; /** * Class WhitelistDeclarationTest @@ -25,22 +27,27 @@ class WhitelistDeclarationTest extends \PHPUnit\Framework\TestCase * @var ComponentRegistrarInterface */ private $componentRegistrar; + /** - * @var Schema + * @var SchemaConfigInterface */ - private $declarativeSchema; + private $schemaConfig; public function setUp() { + /** @var ObjectManagerInterface|ObjectManager $objectManager */ $objectManager = Bootstrap::getObjectManager(); - $schemaConfig = $objectManager->get(SchemaConfigInterface::class); - $this->declarativeSchema = $schemaConfig->getDeclarationConfig(); + $resourceConnection = $objectManager->create(ResourceConnection::class); + $objectManager->removeSharedInstance(ResourceConnection::class); + $objectManager->addSharedInstance($resourceConnection, ResourceConnection::class); $this->componentRegistrar = $objectManager->get(ComponentRegistrarInterface::class); + $this->schemaConfig = $objectManager->create(SchemaConfigInterface::class); } /** * Checks that all declared table elements also declared into whitelist declaration. * + * @appIsolation * @throws \Exception */ public function testConstraintsAndIndexesAreWhitelisted() @@ -48,8 +55,9 @@ public function testConstraintsAndIndexesAreWhitelisted() $undeclaredElements = []; $resultMessage = "New table elements that do not exist in the whitelist declaration:\n"; $whitelistTables = $this->getWhiteListTables(); + $declarativeSchema = $this->schemaConfig->getDeclarationConfig(); - foreach ($this->declarativeSchema->getTables() as $schemaTable) { + foreach ($declarativeSchema->getTables() as $schemaTable) { $tableNameWithoutPrefix = $schemaTable->getNameWithoutPrefix(); foreach ($schemaTable->getConstraints() as $constraint) { $constraintNameWithoutPrefix = $constraint->getNameWithoutPrefix(); From b5feecc4b3886c570094f79ed47ec03a76d0b580 Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya <yksuhagiya@gmail.com> Date: Sat, 26 May 2018 11:21:58 +0530 Subject: [PATCH 0817/2023] Added language translation for message string --- .../Controller/Adminhtml/System/Message/ListAction.php | 6 ++++-- app/code/Magento/AdminNotification/i18n/en_US.csv | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/AdminNotification/Controller/Adminhtml/System/Message/ListAction.php b/app/code/Magento/AdminNotification/Controller/Adminhtml/System/Message/ListAction.php index 303675b968256..d58a7ec31f77d 100644 --- a/app/code/Magento/AdminNotification/Controller/Adminhtml/System/Message/ListAction.php +++ b/app/code/Magento/AdminNotification/Controller/Adminhtml/System/Message/ListAction.php @@ -62,8 +62,10 @@ public function execute() if (empty($result)) { $result[] = [ 'severity' => (string)\Magento\Framework\Notification\MessageInterface::SEVERITY_NOTICE, - 'text' => 'You have viewed and resolved all recent system notices. ' - . 'Please refresh the web page to clear the notice alert.', + 'text' => __( + 'You have viewed and resolved all recent system notices. ' + . 'Please refresh the web page to clear the notice alert.' + ) ]; } /** @var \Magento\Framework\Controller\Result\Json $resultJson */ diff --git a/app/code/Magento/AdminNotification/i18n/en_US.csv b/app/code/Magento/AdminNotification/i18n/en_US.csv index 16c5abb9db0d2..db5a4c9254814 100644 --- a/app/code/Magento/AdminNotification/i18n/en_US.csv +++ b/app/code/Magento/AdminNotification/i18n/en_US.csv @@ -48,3 +48,4 @@ Severity,Severity "Date Added","Date Added" Message,Message Actions,Actions +"You have viewed and resolved all recent system notices. Please refresh the web page to clear the notice alert.","You have viewed and resolved all recent system notices. Please refresh the web page to clear the notice alert." From 60bc9a814ccd0268dd3649e798a7ec3e0bb01350 Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya <yksuhagiya@gmail.com> Date: Sat, 19 May 2018 15:22:57 +0530 Subject: [PATCH 0818/2023] Added language translation for comment tag --- app/code/Magento/Signifyd/etc/adminhtml/system.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Signifyd/etc/adminhtml/system.xml b/app/code/Magento/Signifyd/etc/adminhtml/system.xml index d9ba2f7ffdff2..71f5916ca5325 100644 --- a/app/code/Magento/Signifyd/etc/adminhtml/system.xml +++ b/app/code/Magento/Signifyd/etc/adminhtml/system.xml @@ -13,7 +13,7 @@ <resource>Magento_Sales::fraud_protection</resource> <group id="signifyd" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0"> <fieldset_css>signifyd-logo-header</fieldset_css> - <group id="about" translate="label" sortOrder="15" showInDefault="1" showInWebsite="1" showInStore="0"> + <group id="about" translate="label comment" sortOrder="15" showInDefault="1" showInWebsite="1" showInStore="0"> <frontend_model>Magento\Signifyd\Block\Adminhtml\System\Config\Fieldset\Info</frontend_model> <fieldset_css>signifyd-about-header</fieldset_css> <label><![CDATA[Protect your store from fraud with Guaranteed Fraud Protection by Signifyd.]]></label> @@ -26,12 +26,12 @@ </comment> <more_url>https://www.signifyd.com/magento-guaranteed-fraud-protection</more_url> </group> - <group id="config" translate="label" sortOrder="15" showInDefault="1" showInWebsite="1" showInStore="0"> + <group id="config" translate="label comment" sortOrder="15" showInDefault="1" showInWebsite="1" showInStore="0"> <fieldset_css>signifyd-about-header</fieldset_css> <label>Configuration</label> <comment><![CDATA[<a href="https://www.signifyd.com/resources/manual/magento-2/signifyd-on-magento-integration-guide/" target="_blank">View our setup guide</a> for step-by-step instructions on how to integrate Signifyd with Magento.<br />For support contact <a href="mailto:support@signifyd.com">support@signifyd.com</a>.]]> </comment> - <field id="active" translate="label comment" type="select" showInDefault="1" showInWebsite="1" showInStore="0"> + <field id="active" translate="label" type="select" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Enable this Solution</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> <config_path>fraud_protection/signifyd/active</config_path> From cf05a84f73a36b2fabd08d630e077b6e3ea922f5 Mon Sep 17 00:00:00 2001 From: Hirokazu Nishi <nishi@principle-works.jp> Date: Sat, 26 May 2018 23:01:53 +0900 Subject: [PATCH 0819/2023] fix for Wrong price amount on product page #11717 --- lib/internal/Magento/Framework/Locale/Format.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Locale/Format.php b/lib/internal/Magento/Framework/Locale/Format.php index 7bb4cb4b7d432..8efedf2eaa825 100644 --- a/lib/internal/Magento/Framework/Locale/Format.php +++ b/lib/internal/Magento/Framework/Locale/Format.php @@ -99,7 +99,7 @@ public function getPriceFormat($localeCode = null, $currencyCode = null) $currency = $this->_scopeResolver->getScope()->getCurrentCurrency(); } - $formatter = new \NumberFormatter($localeCode, \NumberFormatter::CURRENCY); + $formatter = new \NumberFormatter($localeCode . '@currency=' . $currency->getCode(), \NumberFormatter::CURRENCY); $format = $formatter->getPattern(); $decimalSymbol = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); $groupSymbol = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); From 973639634fac2107f41e8c799bc8fac62621c02f Mon Sep 17 00:00:00 2001 From: vitaliyboyko <vitaliyboyko@i.ua> Date: Sun, 27 May 2018 16:11:24 +0300 Subject: [PATCH 0820/2023] Fix typos in Multishipping module --- .../Multishipping/Block/Checkout/AbstractMultishipping.php | 2 +- app/code/Magento/Multishipping/Block/Checkout/Shipping.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php b/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php index 0de66ccd505a4..d3c17a8d7c8de 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php +++ b/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php @@ -5,7 +5,7 @@ */ /** - * Mustishipping checkout base abstract block + * Multishipping checkout base abstract block * * @author Magento Core Team <core@magentocommerce.com> */ diff --git a/app/code/Magento/Multishipping/Block/Checkout/Shipping.php b/app/code/Magento/Multishipping/Block/Checkout/Shipping.php index 77981c736b9e9..ef1aa6301b23d 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/Shipping.php +++ b/app/code/Magento/Multishipping/Block/Checkout/Shipping.php @@ -9,7 +9,7 @@ use Magento\Quote\Model\Quote\Address; /** - * Mustishipping checkout shipping + * Multishipping checkout shipping * * @api * @author Magento Core Team <core@magentocommerce.com> From 67a203869a0cff6495bf4953659f0a720cc0641d Mon Sep 17 00:00:00 2001 From: Vishal Gelani <vishalgelani99@gmail.com> Date: Mon, 28 May 2018 12:06:40 +0530 Subject: [PATCH 0821/2023] Fixed line exceeds issue. --- lib/internal/Magento/Framework/Locale/Format.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Locale/Format.php b/lib/internal/Magento/Framework/Locale/Format.php index 8efedf2eaa825..00379c87daaf9 100644 --- a/lib/internal/Magento/Framework/Locale/Format.php +++ b/lib/internal/Magento/Framework/Locale/Format.php @@ -99,7 +99,10 @@ public function getPriceFormat($localeCode = null, $currencyCode = null) $currency = $this->_scopeResolver->getScope()->getCurrentCurrency(); } - $formatter = new \NumberFormatter($localeCode . '@currency=' . $currency->getCode(), \NumberFormatter::CURRENCY); + $formatter = new \NumberFormatter( + $localeCode . '@currency=' . $currency->getCode(), + \NumberFormatter::CURRENCY + ); $format = $formatter->getPattern(); $decimalSymbol = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); $groupSymbol = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); From 4a9562d391fcddfc6ac3437aad9d3837ba8fd460 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Mon, 28 May 2018 11:18:10 +0200 Subject: [PATCH 0822/2023] [fix] getConfiguration() invoked with 1 parameter, 0 required --- app/code/Magento/Ui/Component/Bookmark.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/Component/Bookmark.php b/app/code/Magento/Ui/Component/Bookmark.php index aa1d7a9fb5c0a..db824f11bd4b1 100644 --- a/app/code/Magento/Ui/Component/Bookmark.php +++ b/app/code/Magento/Ui/Component/Bookmark.php @@ -82,11 +82,11 @@ public function prepare() } } - $this->setData('config', array_replace_recursive($config, $this->getConfiguration($this))); + $this->setData('config', array_replace_recursive($config, $this->getConfiguration())); parent::prepare(); - $jsConfig = $this->getConfiguration($this); + $jsConfig = $this->getConfiguration(); $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); } } From b6cb73ca775b92ec38cb708e180ab823e36e80a5 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Mon, 28 May 2018 11:19:26 +0200 Subject: [PATCH 0823/2023] [fix] Class Magento\Ui\Component\Control\ActionPool constructor invoked with 3 parameters, 2 required. --- .../Magento/Ui/Test/Unit/Component/Control/ActionPoolTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/Test/Unit/Component/Control/ActionPoolTest.php b/app/code/Magento/Ui/Test/Unit/Component/Control/ActionPoolTest.php index e18155cd08c53..85226b780aac3 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/Control/ActionPoolTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/Control/ActionPoolTest.php @@ -83,8 +83,7 @@ protected function setUp() $this->items[$this->key] = $this->createPartialMock(\Magento\Ui\Component\Control\Item::class, ['setData']); $this->actionPool = new ActionPool( $this->contextMock, - $this->itemFactoryMock, - $this->toolbarBlockMock + $this->itemFactoryMock ); } From a0c157e7b9470dd23901404c1583ad61d1adee8c Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Mon, 28 May 2018 13:17:23 +0200 Subject: [PATCH 0824/2023] [fix] add missing properties --- app/code/Magento/Widget/Model/Widget/Instance.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/code/Magento/Widget/Model/Widget/Instance.php b/app/code/Magento/Widget/Model/Widget/Instance.php index f21609cb1ef5c..594ec5c0a2289 100644 --- a/app/code/Magento/Widget/Model/Widget/Instance.php +++ b/app/code/Magento/Widget/Model/Widget/Instance.php @@ -96,6 +96,16 @@ class Instance extends \Magento\Framework\Model\AbstractModel */ protected $_relatedCacheTypes; + /** + * @var \Magento\Catalog\Model\Product\Type + */ + protected $_productType; + + /** + * @var \Magento\Widget\Model\Config\Reader + */ + protected $_reader; + /** * @var \Magento\Framework\Escaper */ From 7e69251f88fa793542313487e6cd0564f2b59a79 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Mon, 28 May 2018 13:24:53 +0200 Subject: [PATCH 0825/2023] [fix] reference to invalid class Magento\Backend\Block\Catalog\Product\Widget\Chooser --- .../Magento/Widget/Test/Unit/Model/_files/widget_config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Widget/Test/Unit/Model/_files/widget_config.php b/app/code/Magento/Widget/Test/Unit/Model/_files/widget_config.php index 098fb14c9cec9..697e56cbcbb38 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/_files/widget_config.php +++ b/app/code/Magento/Widget/Test/Unit/Model/_files/widget_config.php @@ -48,7 +48,7 @@ 'type' => 'label', '@' => ['type' => 'complex'], 'helper_block' => [ - 'type' => \Magento\Backend\Block\Catalog\Product\Widget\Chooser::class, + 'type' => \Magento\Catalog\Block\Adminhtml\Product\Widget\Chooser::class, 'data' => ['button' => ['open' => 'Select Product...']], ], 'visible' => '1', From e1c0fa95b264de509e7a25f4bf4d66ba15b222e7 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Mon, 28 May 2018 13:29:39 +0200 Subject: [PATCH 0826/2023] [fix] widget.xml to match fixed class reference --- app/code/Magento/Widget/Test/Unit/Model/_files/widget.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Widget/Test/Unit/Model/_files/widget.xml b/app/code/Magento/Widget/Test/Unit/Model/_files/widget.xml index 02e65707d322f..6deddeca59ef9 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/_files/widget.xml +++ b/app/code/Magento/Widget/Test/Unit/Model/_files/widget.xml @@ -41,7 +41,7 @@ </parameter> <parameter name="id_path" xsi:type="block" visible="true" required="true" sort_order="10"> <label translate="true">Product</label> - <block class="Magento\Backend\Block\Catalog\Product\Widget\Chooser"> + <block class="Magento\Catalog\Block\Adminhtml\Product\Widget\Chooser"> <data> <item name="button" xsi:type="array"> <item name="open" xsi:type="string" translate="true">Select Product...</item> From 65d72bb598e8dba58231f19e3d3990cbbc5a3215 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Mon, 28 May 2018 20:04:43 +0200 Subject: [PATCH 0827/2023] [task] add SuppressWarnings(PHPMD.TooManyFields) --- app/code/Magento/Widget/Model/Widget/Instance.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Widget/Model/Widget/Instance.php b/app/code/Magento/Widget/Model/Widget/Instance.php index 594ec5c0a2289..afe7ef3766f7c 100644 --- a/app/code/Magento/Widget/Model/Widget/Instance.php +++ b/app/code/Magento/Widget/Model/Widget/Instance.php @@ -22,6 +22,7 @@ * @method int getThemeId() * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) * @since 100.0.2 */ class Instance extends \Magento\Framework\Model\AbstractModel From b39774c9eeb2f8a3a5942c036c82967d7186eb59 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Tue, 29 May 2018 09:53:26 +0300 Subject: [PATCH 0828/2023] MAGETWO-90789: [Magento cloud] Custom options should be cleared if custom options in import file is empty --- .../Model/Import/Product/Option.php | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index 245553ea78169..adb660dd118f9 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -1235,7 +1235,7 @@ protected function _importData() $multiRowData = $this->_getMultiRowFormat($rowData); if (!empty($rowData[self::COLUMN_SKU]) && isset($this->_productsSkuToId[$rowData[self::COLUMN_SKU]])) { $this->_rowProductId = $this->_productsSkuToId[$rowData[self::COLUMN_SKU]]; - if (array_key_exists('custom_options', $rowData) && trim($rowData['custom_options']) === "") { + if (array_key_exists('custom_options', $rowData) && trim($rowData['custom_options']) === '') { $optionsToRemove[] = $this->_rowProductId; } } @@ -1273,15 +1273,18 @@ protected function _importData() $this->removeExistingOptions($products, $optionsToRemove); + $types = [ + 'values' => $typeValues, + 'prices' => $typePrices, + 'titles' => $typeTitles, + ]; //Save prepared custom options data. $this->savePreparedCustomOptions( $products, $options, $titles, $prices, - $typeValues, - $typePrices, - $typeTitles + $types ); } @@ -1546,7 +1549,7 @@ private function getExistingOptionTypeId($optionId, $storeId, $optionTypeTitle) */ protected function _parseRequiredData(array $rowData) { - if (!isset($this->_rowProductId)) { + if ($this->_rowProductId === null) { return false; } @@ -2006,9 +2009,7 @@ private function getProductIdentifierField() * @param array $options * @param array $titles * @param array $prices - * @param array $typeValues - * @param array $typePrices - * @param array $typeTitles + * @param array $types * * @return void */ @@ -2017,16 +2018,9 @@ private function savePreparedCustomOptions( array $options, array $titles, array $prices, - array $typeValues, - array $typePrices, - array $typeTitles + array $types ): void { - if ($this->_isReadyForSaving($options, $titles, $typeValues)) { - $types = [ - 'values' => $typeValues, - 'prices' => $typePrices, - 'titles' => $typeTitles, - ]; + if ($this->_isReadyForSaving($options, $titles, $types['values'])) { if ($this->getBehavior() == \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND) { $this->_compareOptionsWithExisting($options, $titles, $prices, $types['values']); $this->restoreOriginalOptionTypeIds($types['values'], $types['prices'], $types['titles']); From 2f82461e0f6af7d49d71c302b68da4b742b991c4 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Tue, 29 May 2018 10:36:09 +0300 Subject: [PATCH 0829/2023] MAGETWO-90784: Catalog Rule is not applied --- .../Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php | 2 +- .../Magento/CatalogRule/Model/Indexer/Product/PriceTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php index 5149fddfc080a..285e1781e2f95 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php @@ -71,7 +71,7 @@ class DefaultPrice extends AbstractIndexer implements PriceInterface * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param \Magento\Framework\Module\Manager $moduleManager * @param string|null $connectionName - * @param IndexTableStructureFactory $indexTableStructureFactory + * @param null|IndexTableStructureFactory $indexTableStructureFactory * @param PriceModifierInterface[] $priceModifiers */ public function __construct( diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/Model/Indexer/Product/PriceTest.php b/dev/tests/integration/testsuite/Magento/CatalogRule/Model/Indexer/Product/PriceTest.php index ad580cfb3aeb5..b1a10c894f83a 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogRule/Model/Indexer/Product/PriceTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/Model/Indexer/Product/PriceTest.php @@ -28,6 +28,9 @@ class PriceTest extends \PHPUnit\Framework\TestCase */ private $resourceRule; + /** + * {@inheritdoc} + */ protected function setUp() { $this->resourceRule = Bootstrap::getObjectManager()->get(Rule::class); From 08f733477be28283233b9218061ce139e3f33c02 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 29 May 2018 10:40:34 +0300 Subject: [PATCH 0830/2023] MAGETWO-90808: [Performance] Customer Import check data does not complete --- .../Test/Unit/Model/Import/CustomerCompositeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php index 9fe8c87a390dc..c19f1ac9e38c9 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php @@ -232,6 +232,7 @@ protected function _getModelMockForImportData($isDeleteBehavior, $customerImport if ($isDeleteBehavior || !$customerImport) { $addressEntity->expects($this->never())->method('importData'); } else { + $addressEntity->expects($this->once())->method('setCustomerAttributes')->will($this->returnSelf()); $addressEntity->expects($this->once())->method('importData')->will($this->returnValue($addressImport)); } @@ -654,7 +655,6 @@ public function dataProviderTestImportData() */ public function testImportData($behavior, $customerImport, $addressImport, $result) { - return; $isDeleteBehavior = $behavior == Import::BEHAVIOR_DELETE; $entityMock = $this->_getModelMockForImportData($isDeleteBehavior, $customerImport, $addressImport); $entityMock->setParameters(['behavior' => $behavior]); From 2a20abd1ffa8d7fef1dfaa0eb1063ac45586d4c2 Mon Sep 17 00:00:00 2001 From: Leandro Ferraz Luvisotto <l.luvisotto@youwe.nl> Date: Tue, 29 May 2018 10:39:15 +0200 Subject: [PATCH 0831/2023] Missing PHPDoc comment --- .../CollectionProcessor/ExtensibleEntityProcessor.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/ExtensibleEntityProcessor.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/ExtensibleEntityProcessor.php index e35c8b3e20c51..365d4f018ef4a 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/ExtensibleEntityProcessor.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product/CollectionProcessor/ExtensibleEntityProcessor.php @@ -32,12 +32,6 @@ public function __construct(JoinProcessorInterface $joinProcessor) $this->joinProcessor = $joinProcessor; } - /** - * @param Collection $collection - * @param SearchCriteriaInterface $searchCriteria - * @param array $attributeNames - * @return Collection - */ public function process( Collection $collection, SearchCriteriaInterface $searchCriteria, From 12f2e936d3fa433b0872886894745c41418f39b6 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Tue, 29 May 2018 14:30:00 +0300 Subject: [PATCH 0832/2023] MAGETWO-89407: [2.3] PayPal Payments Pro settings gets from wrong store --- .../Payflow/Service/Request/SecureToken.php | 2 +- app/code/Magento/Paypal/Model/Payflowlink.php | 3 + .../Service/Request/SecureTokenTest.php | 42 +++- .../Test/Unit/Model/PayflowlinkTest.php | 11 +- .../default_payment_configuration.php | 30 +++ ...default_payment_configuration_rollback.php | 24 ++ .../Paypal/Fixtures/process_config_data.php | 22 ++ .../Fixtures/store_payment_configuration.php | 32 +++ .../store_payment_configuration_rollback.php | 30 +++ .../website_payment_configuration.php | 31 +++ ...website_payment_configuration_rollback.php | 30 +++ .../Service/Request/SecureTokenTest.php | 214 ++++++++++++++++++ .../Paypal/_files/fixed_discount_rollback.php | 26 +++ .../Paypal/_files/quote_payflowpro.php | 16 +- .../_files/quote_payflowpro_rollback.php | 43 ++++ 15 files changed, 535 insertions(+), 21 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Fixtures/default_payment_configuration.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Fixtures/default_payment_configuration_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Fixtures/process_config_data.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Fixtures/store_payment_configuration.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Fixtures/store_payment_configuration_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Fixtures/website_payment_configuration.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Fixtures/website_payment_configuration_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Model/Payflow/Service/Request/SecureTokenTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/_files/fixed_discount_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php diff --git a/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php b/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php index 9d215ca6cbe17..da5599984b701 100644 --- a/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php +++ b/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php @@ -11,7 +11,6 @@ use Magento\Paypal\Model\Payflow\Transparent; use Magento\Paypal\Model\Payflowpro; use Magento\Quote\Model\Quote; -use Magento\Sales\Model\Order\Payment; /** * Class SecureToken @@ -59,6 +58,7 @@ public function __construct( */ public function requestToken(Quote $quote) { + $this->transparent->setStore($quote->getStoreId()); $request = $this->transparent->buildBasicRequest(); $request->setTrxtype(Payflowpro::TRXTYPE_AUTH_ONLY); diff --git a/app/code/Magento/Paypal/Model/Payflowlink.php b/app/code/Magento/Paypal/Model/Payflowlink.php index 792309bd76cf9..1955ef3c67661 100644 --- a/app/code/Magento/Paypal/Model/Payflowlink.php +++ b/app/code/Magento/Paypal/Model/Payflowlink.php @@ -10,6 +10,7 @@ use Magento\Payment\Model\Method\ConfigInterfaceFactory; use Magento\Paypal\Model\Payflow\Service\Response\Handler\HandlerInterface; use Magento\Sales\Api\Data\OrderPaymentInterface; +use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Email\Sender\OrderSender; /** @@ -239,11 +240,13 @@ public function initialize($paymentAction, $stateObject) case \Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH: case \Magento\Paypal\Model\Config::PAYMENT_ACTION_SALE: $payment = $this->getInfoInstance(); + /** @var Order $order */ $order = $payment->getOrder(); $order->setCanSendNewEmailFlag(false); $payment->setAmountAuthorized($order->getTotalDue()); $payment->setBaseAmountAuthorized($order->getBaseTotalDue()); $this->_generateSecureSilentPostHash($payment); + $this->setStore($order->getStoreId()); $request = $this->_buildTokenRequest($payment); $response = $this->postRequest($request, $this->getConfig()); $this->_processTokenErrors($response, $payment); diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Request/SecureTokenTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Request/SecureTokenTest.php index d4a7db25cae89..d8e54ad28fcc8 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Request/SecureTokenTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Request/SecureTokenTest.php @@ -10,6 +10,9 @@ use Magento\Framework\UrlInterface; use Magento\Paypal\Model\Payflow\Service\Request\SecureToken; use Magento\Paypal\Model\Payflow\Transparent; +use Magento\Paypal\Model\PayflowConfig; +use Magento\Quote\Model\Quote; +use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * Test class for \Magento\Paypal\Model\Payflow\Service\Request\SecureToken @@ -19,23 +22,26 @@ class SecureTokenTest extends \PHPUnit\Framework\TestCase /** * @var SecureToken */ - protected $model; + private $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject|Transparent + * @var Transparent|MockObject */ - protected $transparent; + private $transparent; /** - * @var \PHPUnit_Framework_MockObject_MockObject|Random + * @var Random|MockObject */ - protected $mathRandom; + private $mathRandom; /** - * @var \PHPUnit_Framework_MockObject_MockObject|UrlInterface + * @var UrlInterface|MockObject */ - protected $url; + private $url; + /** + * @inheritdoc + */ protected function setUp() { $this->url = $this->createMock(\Magento\Framework\UrlInterface::class); @@ -52,11 +58,29 @@ protected function setUp() public function testRequestToken() { $request = new DataObject(); + $storeId = 1; $secureTokenID = 'Sdj46hDokds09c8k2klaGJdKLl032ekR'; + $response = new DataObject([ + 'result' => '0', + 'respmsg' => 'Approved', + 'securetoken' => '80IgSbabyj0CtBDWHZZeQN3', + 'securetokenid' => $secureTokenID, + 'result_code' => '0', + ]); + + $quote = $this->getMockBuilder(Quote::class) + ->disableOriginalConstructor() + ->getMock(); + $quote->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); $this->transparent->expects($this->once()) ->method('buildBasicRequest') ->willReturn($request); + $this->transparent->expects($this->once()) + ->method('setStore') + ->with($storeId); $this->transparent->expects($this->once()) ->method('fillCustomerContacts'); $this->transparent->expects($this->once()) @@ -64,7 +88,7 @@ public function testRequestToken() ->willReturn($this->createMock(\Magento\Paypal\Model\PayflowConfig::class)); $this->transparent->expects($this->once()) ->method('postRequest') - ->willReturn(new DataObject()); + ->willReturn($response); $this->mathRandom->expects($this->once()) ->method('getUniqueHash') @@ -73,8 +97,6 @@ public function testRequestToken() $this->url->expects($this->exactly(3)) ->method('getUrl'); - $quote = $this->createMock(\Magento\Quote\Model\Quote::class); - $this->model->requestToken($quote); $this->assertEquals($secureTokenID, $request->getSecuretokenid()); diff --git a/app/code/Magento/Paypal/Test/Unit/Model/PayflowlinkTest.php b/app/code/Magento/Paypal/Test/Unit/Model/PayflowlinkTest.php index 362615e965d1b..80c8194e07654 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/PayflowlinkTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/PayflowlinkTest.php @@ -101,16 +101,20 @@ protected function setUp() public function testInitialize() { + $storeId = 1; $order = $this->createMock(\Magento\Sales\Model\Order::class); + $order->expects($this->exactly(2)) + ->method('getStoreId') + ->willReturn($storeId); $this->infoInstance->expects($this->any()) ->method('getOrder') - ->will($this->returnValue($order)); + ->willReturn($order); $this->infoInstance->expects($this->any()) ->method('setAdditionalInformation') - ->will($this->returnSelf()); + ->willReturnSelf(); $this->paypalConfig->expects($this->once()) ->method('getBuildNotationCode') - ->will($this->returnValue('build notation code')); + ->willReturn('build notation code'); $response = new \Magento\Framework\DataObject( [ @@ -148,6 +152,7 @@ public function testInitialize() $stateObject = new \Magento\Framework\DataObject(); $this->model->initialize(\Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH, $stateObject); + self::assertEquals($storeId, $this->model->getStore(), '{Store} should be set'); } /** diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/default_payment_configuration.php b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/default_payment_configuration.php new file mode 100644 index 0000000000000..2c1614b9317c5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/default_payment_configuration.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Config\Model\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/process_config_data.php'; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var EncryptorInterface $encryptor */ +$encryptor = $objectManager->get(EncryptorInterface::class); + +// save payment configuration for the default scope +$configData = [ + 'payment/payflowpro/partner' => 'def_partner', + 'payment/payflowpro/vendor' => 'def_vendor', + 'payment/payflowpro/user' => $encryptor->encrypt('def_user'), + 'payment/payflowpro/pwd' => $encryptor->encrypt('def_pwd'), +]; +/** @var Config $defConfig */ +$defConfig = $objectManager->create(Config::class); +$defConfig->setScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT); +$processConfigData($defConfig, $configData); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/default_payment_configuration_rollback.php b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/default_payment_configuration_rollback.php new file mode 100644 index 0000000000000..b9cf1707c7b6c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/default_payment_configuration_rollback.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\Config\Storage\WriterInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/process_config_data.php'; + +$objectManager = Bootstrap::getObjectManager(); + +$configData = [ + 'payment/payflowpro/partner', + 'payment/payflowpro/vendor', + 'payment/payflowpro/user', + 'payment/payflowpro/pwd', +]; +/** @var WriterInterface $configWriter */ +$configWriter = $objectManager->get(WriterInterface::class); +$deleteConfigData($configWriter, $configData, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, 0); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/process_config_data.php b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/process_config_data.php new file mode 100644 index 0000000000000..2c672378fb832 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/process_config_data.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Config\Model\Config; +use Magento\Framework\App\Config\Storage\WriterInterface; + +$processConfigData = function (Config $config, array $data) { + foreach ($data as $key => $value) { + $config->setDataByPath($key, $value); + $config->save(); + } +}; + +$deleteConfigData = function (WriterInterface $writer, array $configData, string $scope, int $scopeId) { + foreach ($configData as $path) { + $writer->delete($path, $scope, $scopeId); + } +}; diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/store_payment_configuration.php b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/store_payment_configuration.php new file mode 100644 index 0000000000000..e54349e118bb4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/store_payment_configuration.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Config\Model\Config; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\TestFramework\Helper\Bootstrap; + +// save payment configuration per store +require __DIR__ . '/process_config_data.php'; +require __DIR__ . '/../../Store/_files/store.php'; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var EncryptorInterface $encryptor */ +$encryptor = $objectManager->get(EncryptorInterface::class); + +$storeConfigData = [ + 'payment/payflowpro/partner' => 'store_partner', + 'payment/payflowpro/vendor' => 'store_vendor', + 'payment/payflowpro/user' => $encryptor->encrypt('store_user'), + 'payment/payflowpro/pwd' => $encryptor->encrypt('store_pwd'), +]; +/** @var Config $storeConfig */ +$storeConfig = $objectManager->create(Config::class); +$storeConfig->setScope(ScopeInterface::SCOPE_STORES); +$storeConfig->setStore('test'); +$processConfigData($storeConfig, $storeConfigData); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/store_payment_configuration_rollback.php b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/store_payment_configuration_rollback.php new file mode 100644 index 0000000000000..08fe9ca7049f2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/store_payment_configuration_rollback.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\App\Config\Storage\WriterInterface; +use Magento\Store\Api\StoreRepositoryInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/process_config_data.php'; + +$objectManager = Bootstrap::getObjectManager(); + +$configData = [ + 'payment/payflowpro/partner', + 'payment/payflowpro/vendor', + 'payment/payflowpro/user', + 'payment/payflowpro/pwd', +]; +/** @var WriterInterface $configWriter */ +$configWriter = $objectManager->get(WriterInterface::class); + +/** @var StoreRepositoryInterface $storeRepository */ +$storeRepository = $objectManager->get(StoreRepositoryInterface::class); +$store = $storeRepository->get('test'); +$deleteConfigData($configWriter, $configData, ScopeInterface::SCOPE_STORES, (int)$store->getId()); +require __DIR__ . '/../../Store/_files/store_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/website_payment_configuration.php b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/website_payment_configuration.php new file mode 100644 index 0000000000000..90359ccf4fe1c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/website_payment_configuration.php @@ -0,0 +1,31 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Config\Model\Config; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\TestFramework\Helper\Bootstrap; + +// save payment website config data +require __DIR__ . '/../../Store/_files/second_website_with_two_stores.php'; +require __DIR__ . '/process_config_data.php'; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var EncryptorInterface $encryptor */ +$encryptor = $objectManager->get(EncryptorInterface::class); +$websiteConfigData = [ + 'payment/payflowpro/partner' => 'website_partner', + 'payment/payflowpro/vendor' => 'website_vendor', + 'payment/payflowpro/user' => $encryptor->encrypt('website_user'), + 'payment/payflowpro/pwd' => $encryptor->encrypt('website_pwd'), +]; +/** @var Config $websiteConfig */ +$websiteConfig = $objectManager->create(Config::class); +$websiteConfig->setScope(ScopeInterface::SCOPE_WEBSITES); +$websiteConfig->setWebsite($websiteId); +$processConfigData($websiteConfig, $websiteConfigData); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/website_payment_configuration_rollback.php b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/website_payment_configuration_rollback.php new file mode 100644 index 0000000000000..1558d78e2504f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Fixtures/website_payment_configuration_rollback.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\App\Config\Storage\WriterInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/process_config_data.php'; + +$objectManager = Bootstrap::getObjectManager(); + +$configData = [ + 'payment/payflowpro/partner', + 'payment/payflowpro/vendor', + 'payment/payflowpro/user', + 'payment/payflowpro/pwd', +]; +/** @var WriterInterface $configWriter */ +$configWriter = $objectManager->get(WriterInterface::class); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$website = $websiteRepository->get('test'); +$deleteConfigData($configWriter, $configData, ScopeInterface::SCOPE_WEBSITES, (int)$website->getId()); + +require __DIR__ . '/../../Store/_files/second_website_with_two_stores_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Payflow/Service/Request/SecureTokenTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/Payflow/Service/Request/SecureTokenTest.php new file mode 100644 index 0000000000000..df6a1aae3fdb8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Payflow/Service/Request/SecureTokenTest.php @@ -0,0 +1,214 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Paypal\Model\Payflow\Service\Request; + +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\DataObject; +use Magento\Framework\Math\Random; +use Magento\Paypal\Model\Payflow\Service\Gateway; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Quote; +use Magento\Store\Api\Data\StoreInterface; +use Magento\Store\Api\StoreRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +/** + * @magentoAppIsolation enabled + */ +class SecureTokenTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var SecureToken + */ + private $service; + + /** + * @var Gateway|MockObject + */ + private $gateway; + + /** + * @var CartRepositoryInterface + */ + private $quoteRepository; + + /** + * @var Random|MockObject; + */ + private $mathRandom; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + + $this->gateway = $this->getMockBuilder(Gateway::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->quoteRepository = $this->objectManager->get(CartRepositoryInterface::class); + $this->objectManager->addSharedInstance($this->gateway, Gateway::class); + + $this->mathRandom = $this->getMockBuilder(Random::class) + ->getMock(); + + $this->service = $this->objectManager->create( + SecureToken::class, + [ + 'mathRandom' => $this->mathRandom + ] + ); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->objectManager->removeSharedInstance(Gateway::class); + } + + /** + * Checks a case when secure token can be obtained with credentials for the default scope. + * + * @magentoDataFixture Magento/Paypal/_files/quote_payflowpro.php + * @magentoDataFixture Magento/Paypal/Fixtures/default_payment_configuration.php + * @magentoAppArea adminhtml + */ + public function testRequestToken() + { + $quote = $this->getQuote('100000015'); + $quote->setStoreId(null); + $this->execute($quote, 'def_partner', 'def_vendor', 'def_user', 'def_pwd'); + } + + /** + * Checks a case when secure token can be obtained with credentials specified per store. + * + * @magentoDataFixture Magento/Paypal/_files/quote_payflowpro.php + * @magentoDataFixture Magento/Paypal/Fixtures/store_payment_configuration.php + * @magentoAppArea adminhtml + */ + public function testRequestTokenWithStoreConfiguration() + { + $quote = $this->getQuote('100000015'); + $store = $this->getStore('test'); + $quote->setStoreId($store->getId()); + $this->execute($quote, 'store_partner', 'store_vendor', 'store_user', 'store_pwd'); + } + + /** + * Checks a case when secure token can be obtained with credentials specified per website. + * + * @magentoDataFixture Magento/Paypal/_files/quote_payflowpro.php + * @magentoDataFixture Magento/Paypal/Fixtures/website_payment_configuration.php + * @magentoAppArea adminhtml + */ + public function testRequestTokenWithWebsiteConfiguration() + { + $quote = $this->getQuote('100000015'); + $store = $this->getStore('fixture_second_store'); + $quote->setStoreId($store->getId()); + $this->execute($quote, 'website_partner', 'website_vendor', 'website_user', 'website_pwd'); + } + + /** + * Retrieves secure token and perform test assertions. + * + * @param Quote $quote + * @param string $expPartner + * @param string $expVendor + * @param string $expUser + * @param string $expPwd + */ + private function execute(Quote $quote, string $expPartner, string $expVendor, string $expUser, string $expPwd) + { + $secureTokenId = '31f2a7c8d257c70b1c9eb9051b90e0'; + $token = '80IgSbabyj0CtBDWHZZeQN3'; + + $this->mathRandom->method('getUniqueHash') + ->willReturn($secureTokenId); + + $response = new DataObject([ + 'result' => '0', + 'respmsg' => 'Approved', + 'securetoken' => $token, + 'securetokenid' => $secureTokenId, + 'result_code' => '0', + ]); + $self = $this; + $this->gateway->method('postRequest') + /** @var DataObject $request */ + ->with(self::callback(function ($request) use ($self, $expPartner, $expVendor, $expUser, $expPwd) { + $self->performAssertion($expPartner, $request->getPartner(), '{Partner}'); + $self->performAssertion($expVendor, $request->getVendor(), '{Vendor}'); + $self->performAssertion($expUser, $request->getUser(), '{User}'); + $self->performAssertion($expPwd, $request->getPwd(), '{Password}'); + + return true; + })) + ->willReturn($response); + + $response = $this->service->requestToken($quote); + $this->performAssertion($token, $response->getData('securetoken'), '{Secure Token}'); + } + + /** + * Perform assertions test assertions. + * + * @param string $expected + * @param string $actual + * @param string $property + */ + private function performAssertion(string $expected, string $actual, string $property) + { + self::assertEquals($expected, $actual, "$property should match."); + } + + /** + * Loads quote by order increment id. + * + * @param string $orderIncrementId + * @return Quote + */ + private function getQuote(string $orderIncrementId): Quote + { + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilter('reserved_order_id', $orderIncrementId) + ->create(); + + $items = $this->quoteRepository->getList($searchCriteria) + ->getItems(); + + return array_pop($items); + } + + /** + * Loads store by provided code. + * + * @param string $code + * @return StoreInterface + */ + private function getStore(string $code): StoreInterface + { + /** @var StoreRepositoryInterface $storeRepository */ + $storeRepository = $this->objectManager->get(StoreRepositoryInterface::class); + return $storeRepository->get($code); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/fixed_discount_rollback.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/fixed_discount_rollback.php new file mode 100644 index 0000000000000..55ce3be29f7c7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/fixed_discount_rollback.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\ObjectManagerInterface; +use Magento\SalesRule\Api\Data\RuleInterface; +use Magento\SalesRule\Api\RuleRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var ObjectManagerInterface $objectManager */ +$objectManager = Bootstrap::getObjectManager(); +/** @var RuleRepositoryInterface $ruleRepository */ +$ruleRepository = $objectManager->get(RuleRepositoryInterface::class); +/** @var SearchCriteriaBuilder $searchCriteriaBuilder */ +$searchCriteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class); +$searchCriteria = $searchCriteriaBuilder->addFilter('name', '10$ discount')->create(); +$items = $ruleRepository->getList($searchCriteria)->getItems(); + +/** @var RuleInterface $item */ +foreach ($items as $item) { + $ruleRepository->deleteById($item->getRuleId()); +} diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro.php index 9b7e296d12c7d..c95f9df151608 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro.php @@ -5,6 +5,7 @@ */ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\CatalogInventory\Api\Data\StockItemInterface; use Magento\Framework\ObjectManagerInterface; use Magento\Quote\Model\Quote; use Magento\Quote\Model\Quote\Address; @@ -55,15 +56,16 @@ ->setName('Simple ' . $i) ->setSku('simple' . $i) ->setAttributeSetId(4) - ->setStockData( - [ - 'qty' => 10, - 'is_in_stock' => 10, - 'manage_stock' => 1, - ] - ) ->setPrice(5.69 + $i * 2) ->setWeight(1); + + /** @var StockItemInterface $stockItem */ + $stockItem = $objectManager->create(StockItemInterface::class); + $stockItem->setQty(10) + ->setIsInStock(true); + $extensionAttributes = $product->getExtensionAttributes(); + $extensionAttributes->setStockItem($stockItem); + $item = $productRepository->save($product); $quote->addProduct($item, $i); } diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php new file mode 100644 index 0000000000000..42c93f4a4c1e7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\ObjectManagerInterface; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require 'fixed_discount_rollback.php'; + +/** @var ObjectManagerInterface $objectManager */ +$objectManager = Bootstrap::getObjectManager(); + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var SearchCriteriaBuilder $productSearchCriteriaBuilder */ +$productSearchCriteriaBuilder = $objectManager->create(SearchCriteriaBuilder::class); +$searchCriteria = $productSearchCriteriaBuilder->addFilter('sku', ['simple1', 'simple2', 'simple3'], 'in') + ->create(); +$productList = $productRepository->getList($searchCriteria) + ->getItems(); +if (!empty($productList)) { + foreach ($productList as $product) { + $productRepository->delete($product); + } +} + +/** @var CartRepositoryInterface $quoteRepository */ +$quoteRepository = $objectManager->get(CartRepositoryInterface::class); +/** @var SearchCriteriaBuilder $searchCriteriaBuilder */ +$searchCriteriaBuilder = $objectManager->create(SearchCriteriaBuilder::class); +$searchCriteria = $searchCriteriaBuilder->addFilter('reserved_order_id', '100000015')->create(); +$items = $quoteRepository->getList($searchCriteria)->getItems(); + +if (!empty($items)) { + $quote = array_pop($items); + $quoteRepository->delete($quote); +} From d1446bf8de1e9f0c622e9f388bbc22c10a34ce27 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Tue, 29 May 2018 15:15:49 +0300 Subject: [PATCH 0833/2023] MAGETWO-89407: [2.3] PayPal Payments Pro settings gets from wrong store --- .../Magento/Paypal/_files/quote_payflowpro_rollback.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php index 42c93f4a4c1e7..6eded10e5c555 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php @@ -22,8 +22,12 @@ $productSearchCriteriaBuilder = $objectManager->create(SearchCriteriaBuilder::class); $searchCriteria = $productSearchCriteriaBuilder->addFilter('sku', ['simple1', 'simple2', 'simple3'], 'in') ->create(); -$productList = $productRepository->getList($searchCriteria) - ->getItems(); +$productList = $productRepository->getList($searchCriteria)->getItems(); + +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + if (!empty($productList)) { foreach ($productList as $product) { $productRepository->delete($product); From 769352fef70f3b0ce8c8c96ea79bfe0c6cb5a27a Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Tue, 29 May 2018 15:54:04 +0300 Subject: [PATCH 0834/2023] MAGETWO-92134: [2.2.x] Payment Failed Email is not generated --- .../Magento/Authorizenet/Model/Directpost.php | 69 +++- .../Test/Unit/Model/DirectpostTest.php | 51 ++- app/code/Magento/Checkout/Helper/Data.php | 137 +------- .../Checkout/Test/Unit/Helper/DataTest.php | 228 ++++---------- .../Express/AbstractExpress/PlaceOrder.php | 18 +- .../Magento/Paypal/Controller/Payflow.php | 19 +- .../Controller/Transparent/Response.php | 21 +- app/code/Magento/Paypal/Model/Payflowpro.php | 5 +- .../Unit/Controller/Payflow/ReturnUrlTest.php | 19 ++ .../Controller/Transparent/ResponseTest.php | 37 ++- .../Sales/Api/PaymentFailuresInterface.php | 28 ++ .../Sales/Model/Service/OrderService.php | 15 +- .../Model/Service/PaymentFailuresService.php | 295 ++++++++++++++++++ app/code/Magento/Sales/etc/di.xml | 1 + .../Controller/Payflow/SilentPostTest.php | 4 +- .../Magento/Paypal/Controller/PayflowTest.php | 86 +++-- .../Paypal/Controller/PayflowadvancedTest.php | 84 +++-- .../Service/PaymentFailuresServiceTest.php | 98 ++++++ .../testsuite/Magento/Sales/_files/order.php | 94 +++--- .../quote_with_two_products_and_customer.php | 31 ++ 20 files changed, 931 insertions(+), 409 deletions(-) create mode 100644 app/code/Magento/Sales/Api/PaymentFailuresInterface.php create mode 100644 app/code/Magento/Sales/Model/Service/PaymentFailuresService.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer.php diff --git a/app/code/Magento/Authorizenet/Model/Directpost.php b/app/code/Magento/Authorizenet/Model/Directpost.php index 0f10fd633cb5b..de567a8895f7e 100644 --- a/app/code/Magento/Authorizenet/Model/Directpost.php +++ b/app/code/Magento/Authorizenet/Model/Directpost.php @@ -5,10 +5,9 @@ */ namespace Magento\Authorizenet\Model; -use Magento\Framework\HTTP\ZendClientFactory; +use Magento\Framework\App\ObjectManager; use Magento\Payment\Model\Method\ConfigInterface; use Magento\Payment\Model\Method\TransparentInterface; -use Magento\Sales\Model\Order\Email\Sender\OrderSender; /** * Authorize.net DirectPost payment method model. @@ -102,7 +101,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra protected $response; /** - * @var OrderSender + * @var \Magento\Sales\Model\Order\Email\Sender\OrderSender */ protected $orderSender; @@ -123,6 +122,16 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra */ private $psrLogger; + /** + * @var \Magento\Sales\Api\PaymentFailuresInterface + */ + private $paymentFailures; + + /** + * @var \Magento\Sales\Model\Order + */ + private $order; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -141,11 +150,12 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra * @param \Magento\Sales\Model\OrderFactory $orderFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository - * @param OrderSender $orderSender + * @param \Magento\Sales\Model\Order\Email\Sender\OrderSender $orderSender * @param \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data + * @param \Magento\Sales\Api\PaymentFailuresInterface|null $paymentFailures * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -162,7 +172,7 @@ public function __construct( \Magento\Authorizenet\Model\Directpost\Request\Factory $requestFactory, \Magento\Authorizenet\Model\Directpost\Response\Factory $responseFactory, TransactionService $transactionService, - ZendClientFactory $httpClientFactory, + \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory, \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, @@ -170,7 +180,8 @@ public function __construct( \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + \Magento\Sales\Api\PaymentFailuresInterface $paymentFailures = null ) { $this->orderFactory = $orderFactory; $this->storeManager = $storeManager; @@ -179,6 +190,8 @@ public function __construct( $this->orderSender = $orderSender; $this->transactionRepository = $transactionRepository; $this->_code = static::METHOD_CODE; + $this->paymentFailures = $paymentFailures ? : ObjectManager::getInstance() + ->get(\Magento\Sales\Api\PaymentFailuresInterface::class); parent::__construct( $context, @@ -561,13 +574,10 @@ public function process(array $responseData) $this->validateResponse(); $response = $this->getResponse(); - //operate with order - $orderIncrementId = $response->getXInvoiceNum(); $responseText = $this->dataHelper->wrapGatewayError($response->getXResponseReasonText()); $isError = false; - if ($orderIncrementId) { - /* @var $order \Magento\Sales\Model\Order */ - $order = $this->orderFactory->create()->loadByIncrementId($orderIncrementId); + if ($this->getOrderIncrementId()) { + $order = $this->getOrderFromResponse(); //check payment method $payment = $order->getPayment(); if (!$payment || $payment->getMethod() != $this->getCode()) { @@ -632,9 +642,10 @@ public function checkResponseCode() return true; case self::RESPONSE_CODE_DECLINED: case self::RESPONSE_CODE_ERROR: - throw new \Magento\Framework\Exception\LocalizedException( - $this->dataHelper->wrapGatewayError($this->getResponse()->getXResponseReasonText()) - ); + $errorMessage = $this->dataHelper->wrapGatewayError($this->getResponse()->getXResponseReasonText()); + $order = $this->getOrderFromResponse(); + $this->paymentFailures->handle((int)$order->getQuoteId(), $errorMessage); + throw new \Magento\Framework\Exception\LocalizedException($errorMessage); default: throw new \Magento\Framework\Exception\LocalizedException( __('There was a payment authorization error.') @@ -988,12 +999,40 @@ protected function getTransactionResponse($transactionId) private function getPsrLogger() { if (null === $this->psrLogger) { - $this->psrLogger = \Magento\Framework\App\ObjectManager::getInstance() + $this->psrLogger = ObjectManager::getInstance() ->get(\Psr\Log\LoggerInterface::class); } return $this->psrLogger; } + /** + * Fetch order by increment id from response. + * + * @return \Magento\Sales\Model\Order + */ + private function getOrderFromResponse(): \Magento\Sales\Model\Order + { + if (!$this->order) { + $this->order = $this->orderFactory->create(); + + if ($incrementId = $this->getOrderIncrementId()) { + $this->order = $this->order->loadByIncrementId($incrementId); + } + } + + return $this->order; + } + + /** + * Fetch order increment id from response. + * + * @return string + */ + private function getOrderIncrementId(): string + { + return $this->getResponse()->getXInvoiceNum(); + } + /** * Checks if filter action is Report Only. Transactions that trigger this filter are processed as normal, * but are also reported in the Merchant Interface as triggering this filter. diff --git a/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php b/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php index dbb6ac8333c14..95c67f67852da 100644 --- a/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php +++ b/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Authorizenet\Test\Unit\Model; +use Magento\Sales\Api\PaymentFailuresInterface; use Magento\Framework\Simplexml\Element; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Authorizenet\Model\Directpost; @@ -74,6 +75,14 @@ class DirectpostTest extends \PHPUnit\Framework\TestCase */ protected $requestFactory; + /** + * @var PaymentFailuresInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentFailures; + + /** + * @inheritdoc + */ protected function setUp() { $this->scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) @@ -104,6 +113,12 @@ protected function setUp() ->setMethods(['getTransactionDetails']) ->getMock(); + $this->paymentFailures = $this->getMockBuilder( + PaymentFailuresInterface::class + ) + ->disableOriginalConstructor() + ->getMock(); + $this->requestFactory = $this->getRequestFactoryMock(); $httpClientFactoryMock = $this->getHttpClientFactoryMock(); @@ -117,7 +132,8 @@ protected function setUp() 'responseFactory' => $this->responseFactoryMock, 'transactionRepository' => $this->transactionRepositoryMock, 'transactionService' => $this->transactionServiceMock, - 'httpClientFactory' => $httpClientFactoryMock + 'httpClientFactory' => $httpClientFactoryMock, + 'paymentFailures' => $this->paymentFailures, ] ); } @@ -313,12 +329,16 @@ public function checkResponseCodeSuccessDataProvider() } /** - * @param bool $responseCode + * Checks response failures behaviour. + * + * @param int $responseCode + * @param int $failuresHandlerCalls + * @return void * * @expectedException \Magento\Framework\Exception\LocalizedException * @dataProvider checkResponseCodeFailureDataProvider */ - public function testCheckResponseCodeFailure($responseCode) + public function testCheckResponseCodeFailure(int $responseCode, int $failuresHandlerCalls): void { $reasonText = 'reason text'; @@ -333,18 +353,35 @@ public function testCheckResponseCodeFailure($responseCode) ->with($reasonText) ->willReturn(__('Gateway error: %1', $reasonText)); + $orderMock = $this->getMockBuilder(Order::class) + ->disableOriginalConstructor() + ->getMock(); + + $orderMock->expects($this->exactly($failuresHandlerCalls)) + ->method('getQuoteId') + ->willReturn(1); + + $this->paymentFailures->expects($this->exactly($failuresHandlerCalls)) + ->method('handle') + ->with(1); + + $reflection = new \ReflectionClass($this->directpost); + $order = $reflection->getProperty('order'); + $order->setAccessible(true); + $order->setValue($this->directpost, $orderMock); + $this->directpost->checkResponseCode(); } /** * @return array */ - public function checkResponseCodeFailureDataProvider() + public function checkResponseCodeFailureDataProvider(): array { return [ - ['responseCode' => Directpost::RESPONSE_CODE_DECLINED], - ['responseCode' => Directpost::RESPONSE_CODE_ERROR], - ['responseCode' => 999999] + ['responseCode' => Directpost::RESPONSE_CODE_DECLINED, 1], + ['responseCode' => Directpost::RESPONSE_CODE_ERROR, 1], + ['responseCode' => 999999, 0], ]; } diff --git a/app/code/Magento/Checkout/Helper/Data.php b/app/code/Magento/Checkout/Helper/Data.php index b3c2e17e5d678..636d4aaca21f0 100644 --- a/app/code/Magento/Checkout/Helper/Data.php +++ b/app/code/Magento/Checkout/Helper/Data.php @@ -9,6 +9,7 @@ use Magento\Quote\Model\Quote\Item\AbstractItem; use Magento\Store\Model\Store; use Magento\Store\Model\ScopeInterface; +use Magento\Sales\Api\PaymentFailuresInterface; /** * Checkout default helper @@ -52,6 +53,11 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper */ protected $priceCurrency; + /** + * @var PaymentFailuresInterface + */ + private $paymentFailures; + /** * @param \Magento\Framework\App\Helper\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager @@ -60,6 +66,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation * @param PriceCurrencyInterface $priceCurrency + * @param PaymentFailuresInterface|null $paymentFailures * @codeCoverageIgnore */ public function __construct( @@ -69,7 +76,8 @@ public function __construct( \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, - PriceCurrencyInterface $priceCurrency + PriceCurrencyInterface $priceCurrency, + PaymentFailuresInterface $paymentFailures = null ) { $this->_storeManager = $storeManager; $this->_checkoutSession = $checkoutSession; @@ -77,6 +85,8 @@ public function __construct( $this->_transportBuilder = $transportBuilder; $this->inlineTranslation = $inlineTranslation; $this->priceCurrency = $priceCurrency; + $this->paymentFailures = $paymentFailures ? : \Magento\Framework\App\ObjectManager::getInstance() + ->get(PaymentFailuresInterface::class); parent::__construct($context); } @@ -202,126 +212,13 @@ public function getBaseSubtotalInclTax($item) * @param string $message * @param string $checkoutType * @return $this - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function sendPaymentFailedEmail($checkout, $message, $checkoutType = 'onepage') - { - $this->inlineTranslation->suspend(); - - $template = $this->scopeConfig->getValue( - 'checkout/payment_failed/template', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - $checkout->getStoreId() - ); - - $copyTo = $this->_getEmails('checkout/payment_failed/copy_to', $checkout->getStoreId()); - $copyMethod = $this->scopeConfig->getValue( - 'checkout/payment_failed/copy_method', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - $checkout->getStoreId() - ); - $bcc = []; - if ($copyTo && $copyMethod == 'bcc') { - $bcc = $copyTo; - } - - $_receiver = $this->scopeConfig->getValue( - 'checkout/payment_failed/receiver', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - $checkout->getStoreId() - ); - $sendTo = [ - [ - 'email' => $this->scopeConfig->getValue( - 'trans_email/ident_' . $_receiver . '/email', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - $checkout->getStoreId() - ), - 'name' => $this->scopeConfig->getValue( - 'trans_email/ident_' . $_receiver . '/name', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - $checkout->getStoreId() - ), - ], - ]; - - if ($copyTo && $copyMethod == 'copy') { - foreach ($copyTo as $email) { - $sendTo[] = ['email' => $email, 'name' => null]; - } - } - $shippingMethod = ''; - if ($shippingInfo = $checkout->getShippingAddress()->getShippingMethod()) { - $data = explode('_', $shippingInfo); - $shippingMethod = $data[0]; - } - - $paymentMethod = ''; - if ($paymentInfo = $checkout->getPayment()) { - $paymentMethod = $paymentInfo->getMethod(); - } - - $items = ''; - foreach ($checkout->getAllVisibleItems() as $_item) { - /* @var $_item \Magento\Quote\Model\Quote\Item */ - $items .= - $_item->getProduct()->getName() . ' x ' . $_item->getQty() . ' ' . $checkout->getStoreCurrencyCode() - . ' ' . $_item->getProduct()->getFinalPrice( - $_item->getQty() - ) . "\n"; - } - $total = $checkout->getStoreCurrencyCode() . ' ' . $checkout->getGrandTotal(); - - foreach ($sendTo as $recipient) { - $transport = $this->_transportBuilder->setTemplateIdentifier( - $template - )->setTemplateOptions( - [ - 'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, - 'store' => Store::DEFAULT_STORE_ID - ] - )->setTemplateVars( - [ - 'reason' => $message, - 'checkoutType' => $checkoutType, - 'dateAndTime' => $this->_localeDate->formatDateTime( - new \DateTime(), - \IntlDateFormatter::MEDIUM, - \IntlDateFormatter::MEDIUM - ), - 'customer' => $checkout->getCustomerFirstname() . ' ' . $checkout->getCustomerLastname(), - 'customerEmail' => $checkout->getCustomerEmail(), - 'billingAddress' => $checkout->getBillingAddress(), - 'shippingAddress' => $checkout->getShippingAddress(), - 'shippingMethod' => $this->scopeConfig->getValue( - 'carriers/' . $shippingMethod . '/title', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ), - 'paymentMethod' => $this->scopeConfig->getValue( - 'payment/' . $paymentMethod . '/title', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ), - 'items' => nl2br($items), - 'total' => $total, - ] - )->setFrom( - $this->scopeConfig->getValue( - 'checkout/payment_failed/identity', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - $checkout->getStoreId() - ) - )->addTo( - $recipient['email'], - $recipient['name'] - )->addBcc( - $bcc - )->getTransport(); - - $transport->sendMessage(); - } - - $this->inlineTranslation->resume(); + public function sendPaymentFailedEmail( + \Magento\Quote\Model\Quote $checkout, + string $message, + string $checkoutType = 'onepage' + ): \Magento\Checkout\Helper\Data { + $this->paymentFailures->handle((int)$checkout->getId(), $message, $checkoutType); return $this; } diff --git a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php index c403156dc13e9..f6f9ff78c1cb2 100644 --- a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php @@ -6,8 +6,7 @@ namespace Magento\Checkout\Test\Unit\Helper; -use \Magento\Checkout\Helper\Data; - +use Magento\Checkout\Helper\Data; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Store\Model\ScopeInterface; @@ -39,23 +38,21 @@ class DataTest extends \PHPUnit\Framework\TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_checkoutSession; + private $_checkoutSession; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_scopeConfig; + private $_scopeConfig; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_collectionFactory; + private $_eventManager; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @inheritdoc */ - protected $_eventManager; - protected function setUp() { $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -68,59 +65,57 @@ protected function setUp() $this->_scopeConfig = $context->getScopeConfig(); $this->_scopeConfig->expects($this->any()) ->method('getValue') - ->will( - $this->returnValueMap( + ->willReturnMap( + [ + [ + 'checkout/payment_failed/template', + ScopeInterface::SCOPE_STORE, + 8, + 'fixture_email_template_payment_failed', + ], + [ + 'checkout/payment_failed/receiver', + ScopeInterface::SCOPE_STORE, + 8, + 'sysadmin', + ], + [ + 'trans_email/ident_sysadmin/email', + ScopeInterface::SCOPE_STORE, + 8, + 'sysadmin@example.com', + ], + [ + 'trans_email/ident_sysadmin/name', + ScopeInterface::SCOPE_STORE, + 8, + 'System Administrator', + ], + [ + 'checkout/payment_failed/identity', + ScopeInterface::SCOPE_STORE, + 8, + 'noreply@example.com', + ], + [ + 'carriers/ground/title', + ScopeInterface::SCOPE_STORE, + null, + 'Ground Shipping', + ], [ - [ - 'checkout/payment_failed/template', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - 8, - 'fixture_email_template_payment_failed' - ], - [ - 'checkout/payment_failed/receiver', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - 8, - 'sysadmin' - ], - [ - 'trans_email/ident_sysadmin/email', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - 8, - 'sysadmin@example.com' - ], - [ - 'trans_email/ident_sysadmin/name', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - 8, - 'System Administrator' - ], - [ - 'checkout/payment_failed/identity', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - 8, - 'noreply@example.com' - ], - [ - 'carriers/ground/title', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - null, - 'Ground Shipping' - ], - [ - 'payment/fixture-payment-method/title', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - null, - 'Check Money Order' - ], - [ - 'checkout/options/onepage_checkout_enabled', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - null, - 'One Page Checkout' - ] - ] - ) + 'payment/fixture-payment-method/title', + ScopeInterface::SCOPE_STORE, + null, + 'Check Money Order', + ], + [ + 'checkout/options/onepage_checkout_enabled', + ScopeInterface::SCOPE_STORE, + null, + 'One Page Checkout', + ], + ] ); $this->_checkoutSession = $arguments['checkoutSession']; @@ -137,117 +132,16 @@ protected function setUp() /** * @return void - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testSendPaymentFailedEmail() { - $shippingAddress = new \Magento\Framework\DataObject(['shipping_method' => 'ground_transportation']); - $billingAddress = new \Magento\Framework\DataObject(['street' => 'Fixture St']); - - $this->_transportBuilder->expects( - $this->once() - )->method( - 'setTemplateOptions' - )->with( - [ - 'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, - 'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, - ] - )->will( - $this->returnSelf() - ); - - $this->_transportBuilder->expects( - $this->once() - )->method( - 'setTemplateIdentifier' - )->with( - 'fixture_email_template_payment_failed' - )->will( - $this->returnSelf() - ); + $quoteMock = $this->getMockBuilder(\Magento\Quote\Model\Quote::class) + ->setMethods(['getId']) + ->disableOriginalConstructor() + ->getMock(); + $quoteMock->expects($this->any())->method('getId')->willReturn(1); - $this->_transportBuilder->expects( - $this->once() - )->method( - 'setFrom' - )->with( - 'noreply@example.com' - )->will( - $this->returnSelf() - ); - - $this->_transportBuilder->expects( - $this->once() - )->method( - 'addTo' - )->with( - 'sysadmin@example.com', - 'System Administrator' - )->will( - $this->returnSelf() - ); - - $this->_transportBuilder->expects( - $this->once() - )->method( - 'setTemplateVars' - )->with( - [ - 'reason' => 'test message', - 'checkoutType' => 'onepage', - 'dateAndTime' => 'Oct 02, 2013', - 'customer' => 'John Doe', - 'customerEmail' => 'john.doe@example.com', - 'billingAddress' => $billingAddress, - 'shippingAddress' => $shippingAddress, - 'shippingMethod' => 'Ground Shipping', - 'paymentMethod' => 'Check Money Order', - 'items' => "Product One x 2 USD 10<br />\nProduct Two x 3 USD 60<br />\n", - 'total' => 'USD 70' - ] - )->will( - $this->returnSelf() - ); - - $this->_transportBuilder->expects($this->once())->method('addBcc')->will($this->returnSelf()); - $this->_transportBuilder->expects( - $this->once() - )->method( - 'getTransport' - )->will( - $this->returnValue($this->createMock(\Magento\Framework\Mail\TransportInterface::class)) - ); - - $this->_translator->expects($this->at(1))->method('suspend'); - $this->_translator->expects($this->at(1))->method('resume'); - - $productOne = $this->createMock(\Magento\Catalog\Model\Product::class); - $productOne->expects($this->once())->method('getName')->will($this->returnValue('Product One')); - $productOne->expects($this->once())->method('getFinalPrice')->with(2)->will($this->returnValue(10)); - - $productTwo = $this->createMock(\Magento\Catalog\Model\Product::class); - $productTwo->expects($this->once())->method('getName')->will($this->returnValue('Product Two')); - $productTwo->expects($this->once())->method('getFinalPrice')->with(3)->will($this->returnValue(60)); - - $quote = new \Magento\Framework\DataObject( - [ - 'store_id' => 8, - 'store_currency_code' => 'USD', - 'grand_total' => 70, - 'customer_firstname' => 'John', - 'customer_lastname' => 'Doe', - 'customer_email' => 'john.doe@example.com', - 'billing_address' => $billingAddress, - 'shipping_address' => $shippingAddress, - 'payment' => new \Magento\Framework\DataObject(['method' => 'fixture-payment-method']), - 'all_visible_items' => [ - new \Magento\Framework\DataObject(['product' => $productOne, 'qty' => 2]), - new \Magento\Framework\DataObject(['product' => $productTwo, 'qty' => 3]) - ] - ] - ); - $this->assertSame($this->_helper, $this->_helper->sendPaymentFailedEmail($quote, 'test message')); + $this->assertSame($this->_helper, $this->_helper->sendPaymentFailedEmail($quoteMock, 'test message')); } /** diff --git a/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php b/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php index f0fce97da512a..055af4162d5f3 100644 --- a/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php +++ b/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php @@ -21,6 +21,11 @@ class PlaceOrder extends \Magento\Paypal\Controller\Express\AbstractExpress */ protected $agreementsValidator; + /** + * @var \Magento\Sales\Api\PaymentFailuresInterface + */ + private $paymentFailures; + /** * @param \Magento\Framework\App\Action\Context $context * @param \Magento\Customer\Model\Session $customerSession @@ -31,6 +36,8 @@ class PlaceOrder extends \Magento\Paypal\Controller\Express\AbstractExpress * @param \Magento\Framework\Url\Helper\Data $urlHelper * @param \Magento\Customer\Model\Url $customerUrl * @param \Magento\Checkout\Api\AgreementsValidatorInterface $agreementValidator + * @param \Magento\Sales\Api\PaymentFailuresInterface|null $paymentFailures + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Framework\App\Action\Context $context, @@ -41,9 +48,9 @@ public function __construct( \Magento\Framework\Session\Generic $paypalSession, \Magento\Framework\Url\Helper\Data $urlHelper, \Magento\Customer\Model\Url $customerUrl, - \Magento\Checkout\Api\AgreementsValidatorInterface $agreementValidator + \Magento\Checkout\Api\AgreementsValidatorInterface $agreementValidator, + \Magento\Sales\Api\PaymentFailuresInterface $paymentFailures = null ) { - $this->agreementsValidator = $agreementValidator; parent::__construct( $context, $customerSession, @@ -54,6 +61,11 @@ public function __construct( $urlHelper, $customerUrl ); + + $this->agreementsValidator = $agreementValidator; + $this->paymentFailures = $paymentFailures ? : $this->_objectManager->get( + \Magento\Sales\Api\PaymentFailuresInterface::class + ); } /** @@ -148,6 +160,8 @@ private function processException(\Exception $exception, string $message): void */ protected function _processPaypalApiError($exception) { + $this->paymentFailures->handle((int)$this->_getCheckoutSession()->getQuoteId(), $exception->getMessage()); + switch ($exception->getCode()) { case ApiProcessableException::API_MAX_PAYMENT_ATTEMPTS_EXCEEDED: case ApiProcessableException::API_TRANSACTION_EXPIRED: diff --git a/app/code/Magento/Paypal/Controller/Payflow.php b/app/code/Magento/Paypal/Controller/Payflow.php index ab21986bde3ba..78c0536e393ac 100644 --- a/app/code/Magento/Paypal/Controller/Payflow.php +++ b/app/code/Magento/Paypal/Controller/Payflow.php @@ -41,6 +41,11 @@ abstract class Payflow extends \Magento\Framework\App\Action\Action */ protected $_redirectBlockName = 'payflow.link.iframe'; + /** + * @var \Magento\Sales\Api\PaymentFailuresInterface + */ + private $paymentFailures; + /** * @param \Magento\Framework\App\Action\Context $context * @param \Magento\Checkout\Model\Session $checkoutSession @@ -48,6 +53,7 @@ abstract class Payflow extends \Magento\Framework\App\Action\Action * @param \Magento\Paypal\Model\PayflowlinkFactory $payflowModelFactory * @param \Magento\Paypal\Helper\Checkout $checkoutHelper * @param \Psr\Log\LoggerInterface $logger + * @param \Magento\Sales\Api\PaymentFailuresInterface|null $paymentFailures */ public function __construct( \Magento\Framework\App\Action\Context $context, @@ -55,14 +61,19 @@ public function __construct( \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Paypal\Model\PayflowlinkFactory $payflowModelFactory, \Magento\Paypal\Helper\Checkout $checkoutHelper, - \Psr\Log\LoggerInterface $logger + \Psr\Log\LoggerInterface $logger, + \Magento\Sales\Api\PaymentFailuresInterface $paymentFailures = null ) { + parent::__construct($context); + $this->_checkoutSession = $checkoutSession; $this->_orderFactory = $orderFactory; $this->_logger = $logger; $this->_payflowModelFactory = $payflowModelFactory; $this->_checkoutHelper = $checkoutHelper; - parent::__construct($context); + $this->paymentFailures = $paymentFailures ?: $this->_objectManager->get( + \Magento\Sales\Api\PaymentFailuresInterface::class + ); } /** @@ -74,6 +85,10 @@ public function __construct( protected function _cancelPayment($errorMsg = '') { $errorMsg = trim(strip_tags($errorMsg)); + $order = $this->_checkoutSession->getLastRealOrder(); + if ($order->getId()) { + $this->paymentFailures->handle((int)$order->getQuoteId(), $errorMsg); + } $gotoSection = false; $this->_checkoutHelper->cancelCurrentOrder($errorMsg); diff --git a/app/code/Magento/Paypal/Controller/Transparent/Response.php b/app/code/Magento/Paypal/Controller/Transparent/Response.php index 23ac20ca8c87b..c54dd529588b9 100644 --- a/app/code/Magento/Paypal/Controller/Transparent/Response.php +++ b/app/code/Magento/Paypal/Controller/Transparent/Response.php @@ -14,6 +14,8 @@ use Magento\Paypal\Model\Payflow\Service\Response\Transaction; use Magento\Paypal\Model\Payflow\Service\Response\Validator\ResponseValidator; use Magento\Paypal\Model\Payflow\Transparent; +use Magento\Sales\Api\PaymentFailuresInterface; +use Magento\Framework\Session\Generic as Session; /** * Class Response @@ -47,6 +49,16 @@ class Response extends \Magento\Framework\App\Action\Action */ private $transparent; + /** + * @var PaymentFailuresInterface + */ + private $paymentFailures; + + /** + * @var Session + */ + private $sessionTransparent; + /** * Constructor * @@ -56,6 +68,8 @@ class Response extends \Magento\Framework\App\Action\Action * @param ResponseValidator $responseValidator * @param LayoutFactory $resultLayoutFactory * @param Transparent $transparent + * @param Session|null $sessionTransparent + * @param PaymentFailuresInterface|null $paymentFailures */ public function __construct( Context $context, @@ -63,7 +77,9 @@ public function __construct( Transaction $transaction, ResponseValidator $responseValidator, LayoutFactory $resultLayoutFactory, - Transparent $transparent + Transparent $transparent, + Session $sessionTransparent = null, + PaymentFailuresInterface $paymentFailures = null ) { parent::__construct($context); $this->coreRegistry = $coreRegistry; @@ -71,6 +87,8 @@ public function __construct( $this->responseValidator = $responseValidator; $this->resultLayoutFactory = $resultLayoutFactory; $this->transparent = $transparent; + $this->sessionTransparent = $sessionTransparent ?: $this->_objectManager->get(Session::class); + $this->paymentFailures = $paymentFailures ?: $this->_objectManager->get(PaymentFailuresInterface::class); } /** @@ -86,6 +104,7 @@ public function execute() } catch (LocalizedException $exception) { $parameters['error'] = true; $parameters['error_msg'] = $exception->getMessage(); + $this->paymentFailures->handle((int)$this->sessionTransparent->getQuoteId(), $parameters['error_msg']); } $this->coreRegistry->register(Iframe::REGISTRY_KEY, $parameters); diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php index 125aa0f6e65a7..16ba4efc90d6a 100644 --- a/app/code/Magento/Paypal/Model/Payflowpro.php +++ b/app/code/Magento/Paypal/Model/Payflowpro.php @@ -648,6 +648,7 @@ public function buildBasicRequest() * @param DataObject $response * @return void * @throws \Magento\Framework\Exception\LocalizedException + * @throws \Magento\Payment\Gateway\Command\CommandException * @throws \Magento\Framework\Exception\State\InvalidTransitionException */ public function processErrors(DataObject $response) @@ -659,9 +660,9 @@ public function processErrors(DataObject $response) } elseif ($response->getResultCode() != self::RESPONSE_CODE_APPROVED && $response->getResultCode() != self::RESPONSE_CODE_FRAUDSERVICE_FILTER ) { - throw new \Magento\Framework\Exception\LocalizedException(__($response->getRespmsg())); + throw new \Magento\Payment\Gateway\Command\CommandException(__($response->getRespmsg())); } elseif ($response->getOrigresult() == self::RESPONSE_CODE_DECLINED_BY_FILTER) { - throw new \Magento\Framework\Exception\LocalizedException(__($response->getRespmsg())); + throw new \Magento\Payment\Gateway\Command\CommandException(__($response->getRespmsg())); } } diff --git a/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php b/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php index e25864bbc2f3c..bd4da25cb84d0 100644 --- a/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Paypal\Test\Unit\Controller\Payflow; +use Magento\Sales\Api\PaymentFailuresInterface; use Magento\Checkout\Block\Onepage\Success; use Magento\Checkout\Model\Session; use Magento\Framework\App\Action\Context; @@ -90,6 +91,11 @@ class ReturnUrlTest extends \PHPUnit\Framework\TestCase */ private $objectManager; + /** + * @var PaymentFailuresInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentFailures; + /** * @inheritdoc */ @@ -138,6 +144,17 @@ protected function setUp() ->setMethods(['getLastRealOrderId', 'getLastRealOrder', 'restoreQuote']) ->getMock(); + $this->quote = $this->getMockBuilder(CartInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->context->expects($this->any())->method('getView')->willReturn($this->view); + $this->context->expects($this->any())->method('getRequest')->willReturn($this->request); + + $this->paymentFailures = $this->getMockBuilder(PaymentFailuresInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->context->method('getView') ->willReturn($this->view); $this->context->method('getRequest') @@ -148,6 +165,7 @@ protected function setUp() 'checkoutSession' => $this->checkoutSession, 'orderFactory' => $this->orderFactory, 'checkoutHelper' => $this->checkoutHelper, + 'paymentFailures' => $this->paymentFailures, ]); } @@ -321,6 +339,7 @@ public function testCheckAdvancedAcceptingByPaymentMethod() 'checkoutSession' => $this->checkoutSession, 'orderFactory' => $this->orderFactory, 'checkoutHelper' => $this->checkoutHelper, + 'paymentFailures' => $this->paymentFailures, ]); $returnUrl->execute(); diff --git a/app/code/Magento/Paypal/Test/Unit/Controller/Transparent/ResponseTest.php b/app/code/Magento/Paypal/Test/Unit/Controller/Transparent/ResponseTest.php index a10d103860c65..acefebb779200 100644 --- a/app/code/Magento/Paypal/Test/Unit/Controller/Transparent/ResponseTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Controller/Transparent/ResponseTest.php @@ -8,16 +8,16 @@ use Magento\Framework\App\Action\Context; use Magento\Framework\App\RequestInterface; use Magento\Framework\Registry; +use Magento\Framework\Session\Generic as Session; use Magento\Framework\View\Result\Layout; use Magento\Framework\View\Result\LayoutFactory; use Magento\Paypal\Controller\Transparent\Response; use Magento\Paypal\Model\Payflow\Service\Response\Transaction; use Magento\Paypal\Model\Payflow\Service\Response\Validator\ResponseValidator; use Magento\Paypal\Model\Payflow\Transparent; +use Magento\Sales\Api\PaymentFailuresInterface; /** - * Class ResponseTest - * * Test for class \Magento\Paypal\Controller\Transparent\Response * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -53,6 +53,19 @@ class ResponseTest extends \PHPUnit\Framework\TestCase */ private $payflowFacade; + /** + * @var PaymentFailuresInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentFailures; + + /** + * @var Session|\PHPUnit_Framework_MockObject_MockObject + */ + private $sessionTransparent; + + /** + * @inheritdoc + */ protected function setUp() { $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class) @@ -97,6 +110,14 @@ protected function setUp() ->disableOriginalConstructor() ->setMethods([]) ->getMock(); + $this->paymentFailures = $this->getMockBuilder(PaymentFailuresInterface::class) + ->disableOriginalConstructor() + ->setMethods(['handle']) + ->getMock(); + $this->sessionTransparent = $this->getMockBuilder(Session::class) + ->disableOriginalConstructor() + ->setMethods(['getQuoteId']) + ->getMock(); $this->object = new Response( $this->contextMock, @@ -104,7 +125,9 @@ protected function setUp() $this->transactionMock, $this->responseValidatorMock, $this->resultLayoutFactoryMock, - $this->payflowFacade + $this->payflowFacade, + $this->sessionTransparent, + $this->paymentFailures ); } @@ -131,6 +154,8 @@ public function testExecute() $this->resultLayoutMock->expects($this->once()) ->method('getLayout') ->willReturn($this->getLayoutMock()); + $this->paymentFailures->expects($this->never()) + ->method('handle'); $this->assertInstanceOf(\Magento\Framework\Controller\ResultInterface::class, $this->object->execute()); } @@ -156,6 +181,12 @@ public function testExecuteWithException() $this->resultLayoutMock->expects($this->once()) ->method('getLayout') ->willReturn($this->getLayoutMock()); + $this->sessionTransparent->method('getQuoteId') + ->willReturn(1); + $this->paymentFailures->expects($this->once()) + ->method('handle') + ->with(1) + ->willReturnSelf(); $this->assertInstanceOf(\Magento\Framework\Controller\ResultInterface::class, $this->object->execute()); } diff --git a/app/code/Magento/Sales/Api/PaymentFailuresInterface.php b/app/code/Magento/Sales/Api/PaymentFailuresInterface.php new file mode 100644 index 0000000000000..485ff1ffbe248 --- /dev/null +++ b/app/code/Magento/Sales/Api/PaymentFailuresInterface.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Api; + +/** + * Interface for managing payment gateway failures. + */ +interface PaymentFailuresInterface +{ + /** + * Handles payment gateway failures. + * + * @param int $cartId + * @param string $errorMessage + * @param string $checkoutType + * @return PaymentFailuresInterface + */ + public function handle( + int $cartId, + string $errorMessage, + string $checkoutType = 'onepage' + ): PaymentFailuresInterface; +} diff --git a/app/code/Magento/Sales/Model/Service/OrderService.php b/app/code/Magento/Sales/Model/Service/OrderService.php index 1eb3fad11278f..e4a71f028cc82 100644 --- a/app/code/Magento/Sales/Model/Service/OrderService.php +++ b/app/code/Magento/Sales/Model/Service/OrderService.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Model\Service; use Magento\Sales\Api\OrderManagementInterface; +use Magento\Payment\Gateway\Command\CommandException; /** * Class OrderService @@ -49,6 +50,11 @@ class OrderService implements OrderManagementInterface */ protected $orderCommentSender; + /** + * @var \Magento\Sales\Api\PaymentFailuresInterface + */ + private $paymentFailures; + /** * Constructor * @@ -59,6 +65,7 @@ class OrderService implements OrderManagementInterface * @param \Magento\Sales\Model\OrderNotifier $notifier * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param \Magento\Sales\Model\Order\Email\Sender\OrderCommentSender $orderCommentSender + * @param \Magento\Sales\Api\PaymentFailuresInterface|null $paymentFailures */ public function __construct( \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, @@ -67,7 +74,8 @@ public function __construct( \Magento\Framework\Api\FilterBuilder $filterBuilder, \Magento\Sales\Model\OrderNotifier $notifier, \Magento\Framework\Event\ManagerInterface $eventManager, - \Magento\Sales\Model\Order\Email\Sender\OrderCommentSender $orderCommentSender + \Magento\Sales\Model\Order\Email\Sender\OrderCommentSender $orderCommentSender, + \Magento\Sales\Api\PaymentFailuresInterface $paymentFailures = null ) { $this->orderRepository = $orderRepository; $this->historyRepository = $historyRepository; @@ -76,6 +84,8 @@ public function __construct( $this->notifier = $notifier; $this->eventManager = $eventManager; $this->orderCommentSender = $orderCommentSender; + $this->paymentFailures = $paymentFailures ? : \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Sales\Api\PaymentFailuresInterface::class); } /** @@ -192,6 +202,9 @@ public function place(\Magento\Sales\Api\Data\OrderInterface $order) return $this->orderRepository->save($order); //commit } catch (\Exception $e) { + if ($e instanceof CommandException) { + $this->paymentFailures->handle((int)$order->getQuoteId(), __($e->getMessage())); + } throw $e; //rollback; } diff --git a/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php b/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php new file mode 100644 index 0000000000000..2e8da0dadd5b1 --- /dev/null +++ b/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php @@ -0,0 +1,295 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Model\Service; + +use Magento\Backend\App\Area\FrontNameResolver; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Mail\Template\TransportBuilder; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Framework\Translate\Inline\StateInterface; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\Data\CartInterface as Quote; +use Magento\Sales\Api\PaymentFailuresInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\Store; + +/** + * Service is responsible for handling failed payment transactions. + * + * It depends on Stores > Configuration > Sales > Checkout > Payment Failed Emails configuration. + */ +class PaymentFailuresService implements PaymentFailuresInterface +{ + /** + * Store config + * + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * @var StateInterface + */ + private $inlineTranslation; + + /** + * @var TransportBuilder + */ + private $transportBuilder; + + /** + * @var TimezoneInterface + */ + private $localeDate; + + /** + * @var CartRepositoryInterface + */ + private $cartRepository; + + /** + * @param ScopeConfigInterface $scopeConfig + * @param StateInterface $inlineTranslation + * @param TransportBuilder $transportBuilder + * @param TimezoneInterface $localeDate + * @param CartRepositoryInterface $cartRepository + */ + public function __construct( + ScopeConfigInterface $scopeConfig, + StateInterface $inlineTranslation, + TransportBuilder $transportBuilder, + TimezoneInterface $localeDate, + CartRepositoryInterface $cartRepository + ) { + $this->scopeConfig = $scopeConfig; + $this->inlineTranslation = $inlineTranslation; + $this->transportBuilder = $transportBuilder; + $this->localeDate = $localeDate; + $this->cartRepository = $cartRepository; + } + + /** + * Sends an email about failed transaction. + * + * @param int $cartId + * @param string $message + * @param string $checkoutType + * @return PaymentFailuresInterface + */ + public function handle( + int $cartId, + string $message, + string $checkoutType = 'onepage' + ): PaymentFailuresInterface { + $this->inlineTranslation->suspend(); + $quote = $this->cartRepository->get($cartId); + + $template = $this->getConfigValue('checkout/payment_failed/template', $quote); + $receiver = $this->getConfigValue('checkout/payment_failed/receiver', $quote); + $sendTo = [ + [ + 'email' => $this->getConfigValue('trans_email/ident_' . $receiver . '/email', $quote), + 'name' => $this->getConfigValue('trans_email/ident_' . $receiver . '/name', $quote), + ], + ]; + + $copyMethod = $this->getConfigValue('checkout/payment_failed/copy_method', $quote); + $copyTo = $this->getConfigEmails($quote); + + $bcc = []; + if (!empty($copyTo)) { + switch ($copyMethod) { + case 'bcc': + $bcc = $copyTo; + break; + case 'copy': + foreach ($copyTo as $email) { + $sendTo[] = ['email' => $email, 'name' => null]; + } + break; + } + } + + foreach ($sendTo as $recipient) { + $transport = $this->transportBuilder + ->setTemplateIdentifier($template) + ->setTemplateOptions([ + 'area' => FrontNameResolver::AREA_CODE, + 'store' => Store::DEFAULT_STORE_ID, + ]) + ->setTemplateVars($this->getTemplateVars($quote, $message, $checkoutType)) + ->setFrom($this->getSendFrom($quote)) + ->addTo($recipient['email'], $recipient['name']) + ->addBcc($bcc) + ->getTransport(); + + $transport->sendMessage(); + } + + $this->inlineTranslation->resume(); + + return $this; + } + + /** + * Returns mail template variables. + * + * @param Quote $quote + * @param string $message + * @param string $checkoutType + * @return array + */ + private function getTemplateVars(Quote $quote, string $message, string $checkoutType): array + { + return [ + 'reason' => $message, + 'checkoutType' => $checkoutType, + 'dateAndTime' => $this->getLocaleDate(), + 'customer' => $this->getCustomerName($quote), + 'customerEmail' => $quote->getBillingAddress()->getEmail(), + 'billingAddress' => $quote->getBillingAddress(), + 'shippingAddress' => $quote->getShippingAddress(), + 'shippingMethod' => $this->getConfigValue( + 'carriers/' . $this->getShippingMethod($quote) . '/title', + $quote + ), + 'paymentMethod' => $this->getConfigValue( + 'payment/' . $this->getPaymentMethod($quote) . '/title', + $quote + ), + 'items' => implode('<br />', $this->getQuoteItems($quote)), + 'total' => $quote->getCurrency()->getStoreCurrencyCode() . ' ' . $quote->getGrandTotal(), + ]; + } + + /** + * Returns scope config value by config path. + * + * @param string $configPath + * @param Quote $quote + * @return mixed + */ + private function getConfigValue(string $configPath, Quote $quote) + { + return $this->scopeConfig->getValue( + $configPath, + ScopeInterface::SCOPE_STORE, + $quote->getStoreId() + ); + } + + /** + * Returns shipping method from quote. + * + * @param Quote $quote + * @return string + */ + private function getShippingMethod(Quote $quote) + { + $shippingMethod = ''; + if ($shippingInfo = $quote->getShippingAddress()->getShippingMethod()) { + $data = explode('_', $shippingInfo); + $shippingMethod = $data[0]; + } + + return $shippingMethod; + } + + /** + * Returns payment method title from quote. + * + * @param Quote $quote + * @return string + */ + private function getPaymentMethod(Quote $quote) + { + $paymentMethod = ''; + if ($paymentInfo = $quote->getPayment()) { + $paymentMethod = $paymentInfo->getMethod(); + } + + return $paymentMethod; + } + + /** + * Returns quote visible items. + * + * @param Quote $quote + * @return array + */ + private function getQuoteItems(Quote $quote): array + { + $items = []; + foreach ($quote->getAllVisibleItems() as $item) { + $itemData = $item->getProduct()->getName() . ' x ' . $item->getQty() . ' ' . + $quote->getCurrency()->getStoreCurrencyCode() . ' ' . + $item->getProduct()->getFinalPrice($item->getQty()); + $items[] = $itemData; + } + + return $items; + } + + /** + * Gets email values by configuration path. + * + * @param Quote $quote + * @return array|false + */ + private function getConfigEmails(Quote $quote) + { + $configData = $this->getConfigValue('checkout/payment_failed/copy_to', $quote); + if (!empty($configData)) { + return explode(',', $configData); + } + + return false; + } + + /** + * Returns sender identity. + * + * @param Quote $quote + * @return string + */ + private function getSendFrom(Quote $quote): string + { + return $this->getConfigValue('checkout/payment_failed/identity', $quote); + } + + /** + * Returns current locale date and time + * + * @return string + */ + private function getLocaleDate(): string + { + return $this->localeDate->formatDateTime( + new \DateTime(), + \IntlDateFormatter::MEDIUM, + \IntlDateFormatter::MEDIUM + ); + } + + /** + * Returns customer name. + * + * @param Quote $quote + * @return string + */ + private function getCustomerName(Quote $quote): string + { + $customer = __('Guest'); + if (!$quote->getCustomerIsGuest()) { + $customer = $quote->getCustomer()->getFirstname() . ' ' . + $quote->getCustomer()->getLastname(); + } + + return $customer; + } +} diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index ce2948983edbe..ac25cdab22f56 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -65,6 +65,7 @@ <preference for="Magento\Sales\Api\OrderRepositoryInterface" type="Magento\Sales\Model\OrderRepository"/> <preference for="Magento\Sales\Api\OrderManagementInterface" type="Magento\Sales\Model\Service\OrderService"/> <preference for="Magento\Sales\Api\OrderStatusHistoryRepositoryInterface" type="Magento\Sales\Model\Order\Status\HistoryRepository"/> + <preference for="Magento\Sales\Api\PaymentFailuresInterface" type="Magento\Sales\Model\Service\PaymentFailuresService" /> <preference for="Magento\Sales\Api\ShipmentCommentRepositoryInterface" type="Magento\Sales\Model\Order\Shipment\CommentRepository"/> <preference for="Magento\Sales\Api\ShipmentItemRepositoryInterface" type="Magento\Sales\Model\Order\Shipment\ItemRepository"/> <preference for="Magento\Sales\Api\ShipmentRepositoryInterface" type="Magento\Sales\Model\Order\ShipmentRepository"/> diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/Payflow/SilentPostTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Payflow/SilentPostTest.php index b4904c10dc22e..2bebb5bd95bb2 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Controller/Payflow/SilentPostTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Payflow/SilentPostTest.php @@ -8,8 +8,8 @@ use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\DataObject; -use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Logger\Monolog; +use Magento\Payment\Gateway\Command\CommandException; use Magento\Paypal\Model\Payflow\Service\Gateway; use Magento\Paypal\Model\Payflowlink; use Magento\Sales\Api\Data\OrderInterface; @@ -116,7 +116,7 @@ public function testFraudulentNotification() ->getMock(); $this->_objectManager->addSharedInstance($logger, Monolog::class); - $exception = new LocalizedException(__('Response message from PayPal gateway')); + $exception = new CommandException(__('Response message from PayPal gateway')); $logger->expects(self::once()) ->method('critical') ->with(self::equalTo($exception)); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowTest.php index 987f14c8c87e9..367f68ce25872 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowTest.php @@ -5,32 +5,74 @@ */ namespace Magento\Paypal\Controller; +use Magento\Checkout\Model\Session; +use Magento\Paypal\Model\Config; +use Magento\Quote\Model\Quote; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\OrderRepositoryInterface; + /** * @magentoDataFixture Magento/Sales/_files/order.php */ class PayflowTest extends \Magento\TestFramework\TestCase\AbstractController { + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var CartRepositoryInterface + */ + private $quoteRepository; + + /** + * @var OrderInterface + */ + private $order; + + /** + * @inheritdoc + */ protected function setUp() { parent::setUp(); - $order = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Sales\Model\Order::class); - $order->load('100000001', 'increment_id'); - $order->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_PAYFLOWLINK); + /** @var FilterBuilder $filterBuilder */ + $filterBuilder = $this->_objectManager->get(FilterBuilder::class); + $filters = [ + $filterBuilder->setField(OrderInterface::INCREMENT_ID) + ->setValue('100000001') + ->create(), + ]; - $quote = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Quote\Model\Quote::class - )->setStoreId( - $order->getStoreId() - )->save(); + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->_objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilters($filters) + ->create(); - $order->setQuoteId($quote->getId()); - $order->save(); + $this->orderRepository = $this->_objectManager->get(OrderRepositoryInterface::class); + $orders = $this->orderRepository->getList($searchCriteria) + ->getItems(); - $session = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Checkout\Model\Session::class - ); - $session->setLastRealOrderId($order->getRealOrderId())->setLastQuoteId($order->getQuoteId()); + /** @var OrderInterface $order */ + $this->order = array_pop($orders); + $this->order->getPayment()->setMethod(Config::METHOD_PAYFLOWLINK); + + /** @var $quote \Magento\Quote\Model\Quote */ + $quote = $this->_objectManager->create(Quote::class)->setStoreid($this->order->getStoreid()); + + $this->quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class); + $this->quoteRepository->save($quote); + + $this->order->setQuoteId($quote->getId()); + $this->orderRepository->save($this->order); + + $session = $this->_objectManager->get(Session::class); + $session->setLastRealOrderId($this->order->getRealOrderId())->setLastQuoteId($this->order->getQuoteId()); } public function testCancelPaymentActionIsContentGenerated() @@ -65,22 +107,24 @@ public function testFormActionIsContentGenerated() } /** - * @magentoDataFixture Magento/Sales/_files/order.php * @magentoConfigFixture current_store payment/paypal_payflow/active 1 * @magentoConfigFixture current_store paypal/general/business_account merchant_2012050718_biz@example.com + * @return void */ public function testCancelAction() { - $order = $this->_objectManager->create(\Magento\Sales\Model\Order::class); - $session = $this->_objectManager->get(\Magento\Checkout\Model\Session::class); + $orderId = $this->order->getEntityId(); + /** @var \Magento\Sales\Model\Order $order */ + $order = $this->orderRepository->get($orderId); + /** @var $quote \Magento\Quote\Model\Quote */ + $quote = $this->quoteRepository->get($order->getQuoteId()); - $quote = $this->_objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('test02', 'reserved_order_id'); - $order->load('100000001', 'increment_id')->setQuoteId($quote->getId())->save(); + $session = $this->_objectManager->get(Session::class); $session->setQuoteId($quote->getId()); $session->setPaypalStandardQuoteId($quote->getId())->setLastRealOrderId('100000001'); $this->dispatch('paypal/payflow/cancelpayment'); - $order->load('100000001', 'increment_id'); + + $order = $this->_objectManager->create(OrderRepositoryInterface::class)->get($orderId); $this->assertEquals('canceled', $order->getState()); $this->assertEquals($session->getQuote()->getGrandTotal(), $quote->getGrandTotal()); $this->assertEquals($session->getQuote()->getItemsCount(), $quote->getItemsCount()); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowadvancedTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowadvancedTest.php index ae6053a4801b0..7996acc7ed3b0 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowadvancedTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowadvancedTest.php @@ -5,30 +5,75 @@ */ namespace Magento\Paypal\Controller; +use Magento\Checkout\Model\Session; +use Magento\Paypal\Model\Config; +use Magento\Quote\Model\Quote; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\OrderRepositoryInterface; + /** * @magentoDataFixture Magento/Sales/_files/order.php */ class PayflowadvancedTest extends \Magento\TestFramework\TestCase\AbstractController { + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var CartRepositoryInterface + */ + private $quoteRepository; + + /** + * @var OrderInterface + */ + private $order; + + /** + * @inheritdoc + */ protected function setUp() { parent::setUp(); - $order = $this->_objectManager->create(\Magento\Sales\Model\Order::class); - $order->load('100000001', 'increment_id'); - $order->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_PAYFLOWADVANCED); + /** @var FilterBuilder $filterBuilder */ + $filterBuilder = $this->_objectManager->get(FilterBuilder::class); + $filters = [ + $filterBuilder->setField(OrderInterface::INCREMENT_ID) + ->setValue('100000001') + ->create(), + ]; + + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->_objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilters($filters) + ->create(); + + $this->orderRepository = $this->_objectManager->get(OrderRepositoryInterface::class); + $orders = $this->orderRepository->getList($searchCriteria) + ->getItems(); + + /** @var OrderInterface $order */ + $this->order = array_pop($orders); + $this->order->getPayment()->setMethod(Config::METHOD_PAYFLOWLINK); + + /** @var $quote \Magento\Quote\Model\Quote */ + $quote = $this->_objectManager->create(Quote::class) + ->setStoreid($this->order->getStoreid()); - $quote = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Quote\Model\Quote::class - )->setStoreId( - $order->getStoreId() - )->save(); + $this->quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class); + $this->quoteRepository->save($quote); - $order->setQuoteId($quote->getId()); - $order->save(); + $this->order->setQuoteId($quote->getId()); + $this->orderRepository->save($this->order); - $session = $this->_objectManager->create(\Magento\Checkout\Model\Session::class); - $session->setLastRealOrderId($order->getRealOrderId())->setLastQuoteId($order->getQuoteId()); + $session = $this->_objectManager->get(Session::class); + $session->setLastRealOrderId($this->order->getRealOrderId())->setLastQuoteId($this->order->getQuoteId()); } public function testCancelPaymentActionIsContentGenerated() @@ -55,23 +100,24 @@ public function testFormActionIsContentGenerated() } /** - * @magentoDataFixture Magento/Sales/_files/order.php * @magentoConfigFixture current_store payment/paypal_payflow/active 1 * @magentoConfigFixture current_store paypal/general/business_account merchant_2012050718_biz@example.com + * @return void */ public function testCancelAction() { - $order = $this->_objectManager->create(\Magento\Sales\Model\Order::class); - $session = $this->_objectManager->get(\Magento\Checkout\Model\Session::class); + $orderId = $this->order->getEntityId(); + /** @var \Magento\Sales\Model\Order $order */ + $order = $this->orderRepository->get($orderId); + /** @var $quote \Magento\Quote\Model\Quote */ + $quote = $this->quoteRepository->get($order->getQuoteId()); - $quote = $this->_objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('test02', 'reserved_order_id'); - $order->load('100000001', 'increment_id')->setQuoteId($quote->getId())->save(); + $session = $this->_objectManager->get(Session::class); $session->setQuoteId($quote->getId()); $session->setPaypalStandardQuoteId($quote->getId())->setLastRealOrderId('100000001'); $this->dispatch('paypal/payflow/cancelpayment'); - $order->load('100000001', 'increment_id'); + $order = $this->_objectManager->create(OrderRepositoryInterface::class)->get($orderId); $this->assertEquals('canceled', $order->getState()); $this->assertEquals($session->getQuote()->getGrandTotal(), $quote->getGrandTotal()); $this->assertEquals($session->getQuote()->getItemsCount(), $quote->getItemsCount()); diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php new file mode 100644 index 0000000000000..1e334c9660d19 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Model\Service; + +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Quote; +use Magento\Sales\Api\PaymentFailuresInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Tests \Magento\Sales\Api\PaymentFailuresInterface. + */ +class PaymentFailuresServiceTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var PaymentFailuresInterface + */ + private $paymentFailures; + + /** + * @var Quote + */ + private $quote; + + /** + * @var CartRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $cartRepositoryMock; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->quote = Bootstrap::getObjectManager()->create(Quote::class); + $this->cartRepositoryMock = $this->getMockBuilder(CartRepositoryInterface::class) + ->disableOriginalConstructor() + ->setMethods(['get']) + ->getMockForAbstractClass(); + + $this->paymentFailures = Bootstrap::getObjectManager()->create( + PaymentFailuresInterface::class, + [ + 'cartRepository' => $this->cartRepositoryMock, + ] + ); + } + + /** + * @magentoDataFixture Magento/Sales/_files/quote_with_two_products_and_customer.php + * @magentoConfigFixture current_store payment/payflowpro/title Some Title Of The Method + * @magentoConfigFixture current_store carriers/freeshipping/title Some Shipping Method + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * @return void + */ + public function testHandlerWithCustomer() + { + $errorMessage = __('Transaction declined.'); + $checkoutType = 'custom_checkout'; + + $this->quote->load('test01', 'reserved_order_id'); + $this->cartRepositoryMock->method('get') + ->with($this->quote->getId()) + ->willReturn($this->quote); + + $this->paymentFailures->handle((int)$this->quote->getId(), $errorMessage->render()); + + $paymentReflection = new \ReflectionClass($this->paymentFailures); + $templateTimeMethod = $paymentReflection->getMethod('getLocaleDate'); + $templateTimeMethod->setAccessible(true); + + $templateVarsMethod = $paymentReflection->getMethod('getTemplateVars'); + $templateVarsMethod->setAccessible(true); + + $templateVars = $templateVarsMethod->invoke($this->paymentFailures, $this->quote, $errorMessage, $checkoutType); + $expectedVars = [ + 'reason' => $errorMessage, + 'checkoutType' => $checkoutType, + 'dateAndTime' => $templateTimeMethod->invoke($this->paymentFailures), + 'customer' => 'John Smith', + 'customerEmail' => 'aaa@aaa.com', + 'paymentMethod' => 'Some Title Of The Method', + 'shippingMethod' => 'Some Shipping Method', + 'items' => 'Simple Product x 2 USD 10<br />Custom Design Simple Product x 1 USD 10', + 'total' => 'USD 30.0000', + 'billingAddress' => $this->quote->getBillingAddress(), + 'shippingAddress' => $this->quote->getShippingAddress(), + ]; + + $this->assertEquals($expectedVars, $templateVars); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order.php index f1e2afc88b6f8..a1c5f8277762c 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order.php @@ -4,6 +4,13 @@ * See COPYING.txt for license details. */ +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Address as OrderAddress; +use Magento\Sales\Model\Order\Item as OrderItem; +use Magento\Sales\Model\Order\Payment; +use Magento\Store\Model\StoreManagerInterface; + require 'default_rollback.php'; require __DIR__ . '/../../../Magento/Catalog/_files/product_simple.php'; /** @var \Magento\Catalog\Model\Product $product */ @@ -12,57 +19,50 @@ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); -$billingAddress = $objectManager->create(\Magento\Sales\Model\Order\Address::class, ['data' => $addressData]); +$billingAddress = $objectManager->create(OrderAddress::class, ['data' => $addressData]); $billingAddress->setAddressType('billing'); $shippingAddress = clone $billingAddress; $shippingAddress->setId(null)->setAddressType('shipping'); -$payment = $objectManager->create(\Magento\Sales\Model\Order\Payment::class); -$payment->setMethod('checkmo'); -$payment->setAdditionalInformation('last_trans_id', '11122'); -$payment->setAdditionalInformation('metadata', [ - 'type' => 'free', - 'fraudulent' => false -]); +/** @var Payment $payment */ +$payment = $objectManager->create(Payment::class); +$payment->setMethod('checkmo') + ->setAdditionalInformation('last_trans_id', '11122') + ->setAdditionalInformation( + 'metadata', + [ + 'type' => 'free', + 'fraudulent' => false, + ] + ); + +/** @var OrderItem $orderItem */ +$orderItem = $objectManager->create(OrderItem::class); +$orderItem->setProductId($product->getId()) + ->setQtyOrdered(2) + ->setBasePrice($product->getPrice()) + ->setPrice($product->getPrice()) + ->setRowTotal($product->getPrice()) + ->setProductType('simple'); -/** @var \Magento\Sales\Model\Order\Item $orderItem */ -$orderItem = $objectManager->create(\Magento\Sales\Model\Order\Item::class); -$orderItem->setProductId($product->getId())->setQtyOrdered(2); -$orderItem->setBasePrice($product->getPrice()); -$orderItem->setPrice($product->getPrice()); -$orderItem->setRowTotal($product->getPrice()); -$orderItem->setProductType('simple'); +/** @var Order $order */ +$order = $objectManager->create(Order::class); +$order->setIncrementId('100000001') + ->setState(Order::STATE_PROCESSING) + ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PROCESSING)) + ->setSubtotal(100) + ->setGrandTotal(100) + ->setBaseSubtotal(100) + ->setBaseGrandTotal(100) + ->setCustomerIsGuest(true) + ->setCustomerEmail('customer@null.com') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setStoreId($objectManager->get(StoreManagerInterface::class)->getStore()->getId()) + ->addItem($orderItem) + ->setPayment($payment); -/** @var \Magento\Sales\Model\Order $order */ -$order = $objectManager->create(\Magento\Sales\Model\Order::class); -$order->setIncrementId( - '100000001' -)->setState( - \Magento\Sales\Model\Order::STATE_PROCESSING -)->setStatus( - $order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_PROCESSING) -)->setSubtotal( - 100 -)->setGrandTotal( - 100 -)->setBaseSubtotal( - 100 -)->setBaseGrandTotal( - 100 -)->setCustomerIsGuest( - true -)->setCustomerEmail( - 'customer@null.com' -)->setBillingAddress( - $billingAddress -)->setShippingAddress( - $shippingAddress -)->setStoreId( - $objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getStore()->getId() -)->addItem( - $orderItem -)->setPayment( - $payment -); -$order->save(); +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->create(OrderRepositoryInterface::class); +$orderRepository->save($order); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer.php new file mode 100644 index 0000000000000..b3b341c092d69 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer.php @@ -0,0 +1,31 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../Checkout/_files/quote_with_address.php'; + +/** @var \Magento\Quote\Model\Quote $quote */ +$quote->addProduct( + $customDesignProduct->load($customDesignProduct->getId()), + 1 +); + +$quote->getPayment()->setMethod('payflowpro'); +$quote->setIsMultiShipping('0'); +$quote->getShippingAddress()->setShippingMethod('freeshipping_freeshipping'); +$quote->setReservedOrderId('test01'); +$quote->collectTotals() + ->save(); + +/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */ +$quoteIdMask = Bootstrap::getObjectManager() + ->create(\Magento\Quote\Model\QuoteIdMaskFactory::class) + ->create(); +$quoteIdMask->setQuoteId($quote->getId()); +$quoteIdMask->setDataChanges(true); +$quoteIdMask->save(); From 8559900dab7a81c5dc7fd9b7396fb05aa594f8c1 Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Tue, 29 May 2018 16:15:40 +0300 Subject: [PATCH 0835/2023] MAGETWO-92134: [2.2.x] Payment Failed Email is not generated --- app/code/Magento/Checkout/composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Checkout/composer.json b/app/code/Magento/Checkout/composer.json index 5f695adc9f4b4..540565345bd9b 100644 --- a/app/code/Magento/Checkout/composer.json +++ b/app/code/Magento/Checkout/composer.json @@ -7,7 +7,6 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/framework": "*", - "magento/module-backend": "*", "magento/module-catalog": "*", "magento/module-catalog-inventory": "*", "magento/module-config": "*", From b96c338b1a0feeedabc0ebfa017bf5ece1afdba9 Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Tue, 29 May 2018 16:46:29 +0300 Subject: [PATCH 0836/2023] MAGETWO-90370: Automate with MFTF Gift Options --- .../Section/CheckoutCartProductSection.xml | 8 ++++++++ .../Section/CheckoutCartSummarySection.xml | 2 ++ .../Section/CheckoutOrderSummarySection.xml | 5 +++++ .../Section/StorefrontMiniCartSection.xml | 11 +++++++++++ .../Sales/Page/AdminOrderDetailsPage.xml | 1 + .../Section/AdminOrderGiftOptionSection.xml | 16 ++++++++++++++++ 6 files changed, 43 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Section/AdminOrderGiftOptionSection.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml index 92c10ca83a76d..76cdca91dd600 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml @@ -26,5 +26,13 @@ parameterized="true"/> <element name="RemoveItem" type="button" selector="//table[@id='shopping-cart-table']//tbody//tr[contains(@class,'item-actions')]//a[contains(@class,'action-delete')]"/> + <element name="giftOption" type="text" selector="//tr[contains(., '{{var1}}')]/following-sibling::*[contains(., '{{var2}}')]" parameterized="true"/> + <element name="giftOptionAll" type="text" selector="//div[contains(@class,'cart-gift-item')][contains(., '{{var1}}')]" parameterized="true"/> + <element name="clickGiftOptionsItem" type="button" selector=".gift-options-cart-item .action-gift"/> + <element name="clickGiftOptionsAll" type="button" selector=".gift-item-block .title span"/> + <element name="visibleSmallImageAll" type="text" selector=".gift-item-block .gift-options-content img"/> + <element name="visibleSmallImageItems" type="text" selector="#shopping-cart-table .gift-options-content img"/> + <element name="giftMessageAll" type="block" selector=".cart-gift-item .gift-message"/> + <element name="giftMessageItem" type="block" selector="#shopping-cart-table .gift-options .gift-message"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml index df236692d0d68..c63d761b5381d 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml @@ -14,5 +14,7 @@ <element name="shipping" type="text" selector="//*[@id='cart-totals']//tr[@class='totals shipping excl']//td//span[@class='price']"/> <element name="total" type="text" selector="//*[@id='cart-totals']//tr[@class='grand totals']//td//span[@class='price']"/> <element name="proceedToCheckout" type="button" selector=".action.primary.checkout span" timeout="30"/> + <element name="giftWrappingOrderPrice" type="text" selector="//tr[@class='totals giftwrapping']//td[@data-th='Gift Wrapping for Order']"/> + <element name="giftPrintedCardPrice" type="text" selector="//tr[@class='totals giftwrapping']//td[@data-th='Printed Card']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutOrderSummarySection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutOrderSummarySection.xml index 44bd86065b808..b124a2de8c151 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutOrderSummarySection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutOrderSummarySection.xml @@ -13,5 +13,10 @@ <element name="productItemName" type="text" selector=".product-item-name"/> <element name="productItemQty" type="text" selector=".value"/> <element name="productItemPrice" type="text" selector=".price"/> + <element name="giftWrappingName" type="text" selector=".gift-wrapping-name"/> + <element name="giftWrappingReqularPrice" type="text" selector=".gift-wrapping-title .regular-price span"/> + <element name="giftRemoveButton" type="button" selector=".gift-wrapping-title .action-remove"/> + <element name="clickImage" type="text" selector=".gift-wrapping-preview"/> + <element name="clickButtonGiftUpdate" type="button" selector=".gift-options .actions-toolbar button[type='submit']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/StorefrontMiniCartSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/StorefrontMiniCartSection.xml index bdd97130a9715..028e7ceef68c7 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/StorefrontMiniCartSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/StorefrontMiniCartSection.xml @@ -23,5 +23,16 @@ <element name="viewAndEditCart" type="button" selector=".action.viewcart" timeout="30"/> <element name="miniCartItemsText" type="text" selector=".minicart-items"/> <element name="deleteMiniCartItem" type="button" selector=".action.delete" timeout="30"/> + <element name="giftWrapping" type="text" selector="//*[@id='cart-totals']//tr[@class='totals giftwrapping']//td[@class='amount']"/> + <element name="giftReceipt" type="text" selector=".gift-receipt label span"/> + <element name="giftReceiptCheckbox" type="checkbox" selector=".gift-receipt input"/> + <element name="giftPrintedCardCheckbox" type="checkbox" selector=".gift-printed-card input"/> + <element name="giftMessageTo" type="input" selector=".cart-gift-item .gift-message .gift-options-content .field-to input"/> + <element name="giftMessageFrom" type="input" selector=".cart-gift-item .gift-message .gift-options-content .field-from input"/> + <element name="giftMessage" type="textarea" selector=".cart-gift-item .gift-message .gift-options-content .text textarea"/> + <element name="giftWrappingNameResult" type="text" selector=".gift-summary .gift-wrapping-summary .gift-wrapping-name"/> + <element name="giftWrappingPriceResult" type="text" selector="//*[contains(., '{{var1}}')]/../span[@class='regular-price']//span[contains(., '{{var2}}')]" parameterized="true"/> + <element name="giftReceiptResult" type="text" selector=".gift-wrapping-summary span.label"/> + <element name="giftMessageResult" type="text" selector=".gift-message-summary span"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Page/AdminOrderDetailsPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Page/AdminOrderDetailsPage.xml index df8f4ed63787c..0c8338b898670 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Page/AdminOrderDetailsPage.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Page/AdminOrderDetailsPage.xml @@ -22,5 +22,6 @@ <section name="AdminOrderShipmentsTabSection"/> <section name="AdminOrderCommentsTabSection"/> <section name="AdminOrderTotalSection"/> + <section name="AdminOrderGiftOptionSection"/> </page> </pages> \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Section/AdminOrderGiftOptionSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Section/AdminOrderGiftOptionSection.xml new file mode 100644 index 0000000000000..946f3f132e7a6 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Section/AdminOrderGiftOptionSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> + <!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + --> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> + <section name="AdminOrderGiftOptionSection"> + <element name="giftOptionsImage" type="file" selector=".order-gift-options img"/> + <element name="giftWrappingDesignName" type="text" selector="//div[contains(@class, 'gift-wrapping-design')]/span"/> + <element name="giftWrappingDesignPrice" type="text" selector=".gift-wrapping-design #price-box span .price"/> + </section> +</sections> From b15e6dea6c32288cd307d625a902bc74c2d97427 Mon Sep 17 00:00:00 2001 From: Joan He <johe@magento.com> Date: Tue, 29 May 2018 09:19:48 -0500 Subject: [PATCH 0837/2023] =?UTF-8?q?MAGETWO-91545:=20404=20Error=20not=20?= =?UTF-8?q?found=20page=20=E2=80=9D=20issue=20in=20change=20status=20and?= =?UTF-8?q?=20update=20attribute=20from=20product=20grid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Enable strict type mode to new files --- .../Test/Unit/Ui/Component/Product/MassActionTest.php | 4 +++- .../Magento/Catalog/Ui/Component/Product/MassAction.php | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/Component/Product/MassActionTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/Component/Product/MassActionTest.php index 6ddaed1aeceb6..9d6cf23570fc4 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/Component/Product/MassActionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/Component/Product/MassActionTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Test\Unit\Ui\Component\Product; use Magento\Catalog\Ui\Component\Product\MassAction; @@ -93,7 +95,7 @@ public function testPrepare($componentName, $componentData, $isAllowed = true, $ * @return array * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function getPrepareDataProvider() + public function getPrepareDataProvider() : array { return [ [ diff --git a/app/code/Magento/Catalog/Ui/Component/Product/MassAction.php b/app/code/Magento/Catalog/Ui/Component/Product/MassAction.php index e54c91975f1fb..b7602ec72c915 100644 --- a/app/code/Magento/Catalog/Ui/Component/Product/MassAction.php +++ b/app/code/Magento/Catalog/Ui/Component/Product/MassAction.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Ui\Component\Product; use Magento\Framework\AuthorizationInterface; @@ -43,7 +45,7 @@ public function __construct( /** * {@inheritdoc} */ - public function prepare() + public function prepare() : void { $config = $this->getConfiguration(); @@ -67,7 +69,7 @@ public function prepare() /** * {@inheritdoc} */ - public function getComponentName() + public function getComponentName() : string { return static::NAME; } @@ -78,7 +80,7 @@ public function getComponentName() * @param string $actionType * @return bool */ - private function isActionAllowed($actionType) + private function isActionAllowed($actionType) : bool { $isAllowed = true; switch ($actionType) { From 67ad1659e6c907bf452ab9263b3df5456b09ef05 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Tue, 29 May 2018 17:08:59 +0200 Subject: [PATCH 0838/2023] DocBloc typo fixes --- app/code/Magento/Config/Block/System/Config/Form.php | 2 +- .../Model/Import/Product/Type/Configurable.php | 2 +- app/code/Magento/Customer/Model/Session.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Config/Block/System/Config/Form.php b/app/code/Magento/Config/Block/System/Config/Form.php index c17df229cf549..81e39a83296d7 100644 --- a/app/code/Magento/Config/Block/System/Config/Form.php +++ b/app/code/Magento/Config/Block/System/Config/Form.php @@ -709,7 +709,7 @@ protected function _getAdditionalElementTypes() } /** - * Temporary moved those $this->getRequest()->getParam('blabla') from the code accross this block + * Temporary moved those $this->getRequest()->getParam('blabla') from the code across this block * to getBlala() methods to be later set from controller with setters */ diff --git a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php index 64a0c23139c01..151bf5aa9263e 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php @@ -629,7 +629,7 @@ protected function _insertData() } /** - * Get new supper attribute id. + * Get new super attribute id. * * @return int */ diff --git a/app/code/Magento/Customer/Model/Session.php b/app/code/Magento/Customer/Model/Session.php index 71b0297fdd114..680e68b5c4c0f 100644 --- a/app/code/Magento/Customer/Model/Session.php +++ b/app/code/Magento/Customer/Model/Session.php @@ -555,7 +555,7 @@ public function setAfterAuthUrl($url) } /** - * Reset core session hosts after reseting session ID + * Reset core session hosts after resetting session ID * * @return $this */ From 154fc4007c264fcf456c58d63691fcf8ef9b6adb Mon Sep 17 00:00:00 2001 From: Tom Richards <tom.r@delegator.com> Date: Wed, 16 May 2018 20:46:22 -0400 Subject: [PATCH 0839/2023] Fix typo in Image::open exception message --- lib/internal/Magento/Framework/Image.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Image.php b/lib/internal/Magento/Framework/Image.php index 183f57ca26f69..5dc1969559fdd 100644 --- a/lib/internal/Magento/Framework/Image.php +++ b/lib/internal/Magento/Framework/Image.php @@ -49,7 +49,7 @@ public function open() $this->_adapter->checkDependencies(); if (!file_exists($this->_fileName)) { - throw new \Exception("File '{$this->_fileName}' does not exists."); + throw new \Exception("File '{$this->_fileName}' does not exist."); } $this->_adapter->open($this->_fileName); From 6a0f4ca056425fa2a5d4722a942ae2e08b95ed84 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Thu, 17 May 2018 09:35:17 +0200 Subject: [PATCH 0840/2023] typo in method name from Nvp class --- app/code/Magento/Paypal/Model/Api/Nvp.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Paypal/Model/Api/Nvp.php b/app/code/Magento/Paypal/Model/Api/Nvp.php index 25883590350f4..09b305330d752 100644 --- a/app/code/Magento/Paypal/Model/Api/Nvp.php +++ b/app/code/Magento/Paypal/Model/Api/Nvp.php @@ -844,7 +844,7 @@ public function callGetExpressCheckoutDetails() $request = $this->_exportToRequest($this->_getExpressCheckoutDetailsRequest); $response = $this->call(self::GET_EXPRESS_CHECKOUT_DETAILS, $request); $this->_importFromResponse($this->_paymentInformationResponse, $response); - $this->_exportAddressses($response); + $this->_exportAddresses($response); } /** @@ -1462,7 +1462,7 @@ protected function _exportLineItems(array &$request, $i = 0) * @param array $data * @return void */ - protected function _exportAddressses($data) + protected function _exportAddresses($data) { $address = new \Magento\Framework\DataObject(); \Magento\Framework\DataObject\Mapper::accumulateByMap($data, $address, $this->_billingAddressMap); From b4398ae7ea7fc0cfc4211961a91705495861a1d9 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Fri, 18 May 2018 09:29:39 +0200 Subject: [PATCH 0841/2023] add deprecated notice to misspelled method --- app/code/Magento/Paypal/Model/Api/Nvp.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/code/Magento/Paypal/Model/Api/Nvp.php b/app/code/Magento/Paypal/Model/Api/Nvp.php index 09b305330d752..624068395394d 100644 --- a/app/code/Magento/Paypal/Model/Api/Nvp.php +++ b/app/code/Magento/Paypal/Model/Api/Nvp.php @@ -1456,6 +1456,19 @@ protected function _exportLineItems(array &$request, $i = 0) return parent::_exportLineItems($request, $i); } + /** + * Create billing and shipping addresses basing on response data + * + * @param array $data + * @return void + * @deprecated 100.2.2 typo in method name + * @see _exportAddresses + */ + protected function _exportAddressses($data) + { + $this->_exportAddresses($data); + } + /** * Create billing and shipping addresses basing on response data * From 784099e7ec3276ce3e3dc24d498c3e3a3445cf4c Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Thu, 17 May 2018 09:42:41 +0200 Subject: [PATCH 0842/2023] typo in method name _getCharg[e]ableOptionPrice --- .../Catalog/Model/Product/Option/Type/DefaultType.php | 6 +++--- .../Magento/Catalog/Model/Product/Option/Type/Select.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php b/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php index 51480e849d9f3..cdb3338d4bc06 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php @@ -341,7 +341,7 @@ public function getOptionPrice($optionValue, $basePrice) { $option = $this->getOption(); - return $this->_getChargableOptionPrice($option->getPrice(), $option->getPriceType() == 'percent', $basePrice); + return $this->_getChargeableOptionPrice($option->getPrice(), $option->getPriceType() == 'percent', $basePrice); } /** @@ -395,14 +395,14 @@ public function getProductOptions() } /** - * Return final chargable price for option + * Return final chargeable price for option * * @param float $price Price of option * @param boolean $isPercent Price type - percent or fixed * @param float $basePrice For percent price type * @return float */ - protected function _getChargableOptionPrice($price, $isPercent, $basePrice) + protected function _getChargeableOptionPrice($price, $isPercent, $basePrice) { if ($isPercent) { return $basePrice * $price / 100; diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php index 0ace0372c43bb..4a257a4781063 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php @@ -231,7 +231,7 @@ public function getOptionPrice($optionValue, $basePrice) foreach (explode(',', $optionValue) as $value) { $_result = $option->getValueById($value); if ($_result) { - $result += $this->_getChargableOptionPrice( + $result += $this->_getChargeableOptionPrice( $_result->getPrice(), $_result->getPriceType() == 'percent', $basePrice @@ -246,7 +246,7 @@ public function getOptionPrice($optionValue, $basePrice) } elseif ($this->_isSingleSelection()) { $_result = $option->getValueById($optionValue); if ($_result) { - $result = $this->_getChargableOptionPrice( + $result = $this->_getChargeableOptionPrice( $_result->getPrice(), $_result->getPriceType() == 'percent', $basePrice From 382d6854e94000e2bc74b13f3a82df12ae51bfa7 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Fri, 18 May 2018 09:23:29 +0200 Subject: [PATCH 0843/2023] add deprecated notice to misspelled method --- .../Model/Product/Option/Type/DefaultType.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php b/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php index cdb3338d4bc06..2390a049fbeb6 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/DefaultType.php @@ -394,6 +394,19 @@ public function getProductOptions() return []; } + /** + * @param float $price Price of option + * @param boolean $isPercent Price type - percent or fixed + * @param float $basePrice For percent price type + * @return float + * @deprecated 102.0.4 typo in method name + * @see _getChargeableOptionPrice + */ + protected function _getChargableOptionPrice($price, $isPercent, $basePrice) + { + return $this->_getChargeableOptionPrice($price, $isPercent, $basePrice); + } + /** * Return final chargeable price for option * From 751c3e609e4529d96c64c0c06c6e84efcdec5f92 Mon Sep 17 00:00:00 2001 From: neeta-wagento <neeta@wagento.com> Date: Sat, 19 May 2018 10:47:00 +0530 Subject: [PATCH 0844/2023] set alignment purchase order form and place order button --- .../web/css/source/module/checkout/_payments.less | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less index 3136056d9426d..188fff9379b18 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less @@ -46,6 +46,11 @@ .lib-css(border-top, @checkout-payment-method-title__border); } } + form{ + &.form-purchase-order { + margin-bottom: 15px; + } + } } .payment-method-content { From fb0f192c767f3f8e30a7c861108768d35fbc8b24 Mon Sep 17 00:00:00 2001 From: Piyush Dankhara <dankhrapiyush@gmail.com> Date: Mon, 21 May 2018 19:35:34 +0530 Subject: [PATCH 0845/2023] Update _payments.less Added space --- .../web/css/source/module/checkout/_payments.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less index 188fff9379b18..c7fa7a62fd68e 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less @@ -46,7 +46,7 @@ .lib-css(border-top, @checkout-payment-method-title__border); } } - form{ + form { &.form-purchase-order { margin-bottom: 15px; } From 6e3acbc0a00b2efe7cd4344e312ab7289cfa7f06 Mon Sep 17 00:00:00 2001 From: Sanjay Patel <sanjay@wagento.com> Date: Sat, 19 May 2018 12:41:34 +0530 Subject: [PATCH 0846/2023] #12820 - Wrong annotation in _toOptionArray - magento/framework/Data/Collection/AbstractDb.php --- lib/internal/Magento/Framework/Data/Collection/AbstractDb.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 4feaf21d2b2e8..63ba6824e5ab9 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -630,7 +630,7 @@ public function fetchItem() /** * Overridden to use _idFieldName by default. * - * @param null $valueField + * @param string|null $valueField * @param string $labelField * @param array $additional * @return array From deb14f9717a3f51362659f761db3f7b454c734ac Mon Sep 17 00:00:00 2001 From: RyanZolper <zolper11@gmail.com> Date: Tue, 29 May 2018 13:06:37 -0500 Subject: [PATCH 0847/2023] test for validation hint on textfield custom product option --- .../ActionGroup/AdminProductActionGroup.xml | 34 ++++++++++++++ .../StorefrontProductPageActionGroup.xml | 17 +++++++ ...AdminProductCustomizableOptionsSection.xml | 6 +++ .../Section/StorefrontProductPageSection.xml | 2 + ...bleOptionTextInputLengthValidationHint.xml | 46 +++++++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/ConfigurableOptionTextInputLengthValidationHint.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminProductActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminProductActionGroup.xml index c4843260f9310..22835c7fa2e54 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminProductActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminProductActionGroup.xml @@ -139,6 +139,40 @@ <seeInField userInput="{{simpleProduct.urlKey}}" selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="assertFieldUrlKey"/> </actionGroup> + <!--Fill fields for simple product in a category in Admin, including text option with char limit--> + <actionGroup name="AdminCreateSimpleProductWithTextOptionCharLimit"> + <arguments> + <argument name="category"/> + <argument name="simpleProduct"/> + <argument name="charLimit"/> + </arguments> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> + <click selector="{{AdminProductGridActionSection.addProductToggle}}" stepKey="clickAddProductDropdown"/> + <click selector="{{AdminProductGridActionSection.addSimpleProduct}}" stepKey="clickAddSimpleProduct"/> + <fillField userInput="{{simpleProduct.name}}" selector="{{AdminProductFormSection.productName}}" stepKey="fillName"/> + <fillField userInput="{{simpleProduct.sku}}" selector="{{AdminProductFormSection.productSku}}" stepKey="fillSKU"/> + <fillField userInput="{{simpleProduct.price}}" selector="{{AdminProductFormSection.productPrice}}" stepKey="fillPrice"/> + <fillField userInput="{{simpleProduct.quantity}}" selector="{{AdminProductFormSection.productQuantity}}" stepKey="fillQuantity"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[{{category.name}}]" stepKey="searchAndSelectCategory"/> + <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="openSeoSection"/> + <fillField userInput="{{simpleProduct.urlKey}}" selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="fillUrlKey"/> + + <click selector="{{AdminProductCustomizableOptionsSection.customezableOptions}}" stepKey="openCustomOptionsSection"/> + <click selector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" stepKey="clickAddOption"/> + <fillField userInput="option1" selector="{{AdminProductCustomizableOptionsSection.optionTitleInput}}" stepKey="fillOptionTitle"/> + <click selector="{{AdminProductCustomizableOptionsSection.optionTypeOpenDropDown}}" stepKey="openTypeDropDown"/> + <click selector="{{AdminProductCustomizableOptionsSection.optionTypeTextField}}" stepKey="selectTypeTextField"/> + <fillField userInput="20" selector="{{AdminProductCustomizableOptionsSection.maxCharactersInput}}" stepKey="fillMaxChars"/> + + <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/> + <seeElement selector="{{AdminProductMessagesSection.successMessage}}" stepKey="assertSaveMessageSuccess"/> + <seeInField userInput="{{simpleProduct.name}}" selector="{{AdminProductFormSection.productName}}" stepKey="assertFieldName"/> + <seeInField userInput="{{simpleProduct.sku}}" selector="{{AdminProductFormSection.productSku}}" stepKey="assertFieldSku"/> + <seeInField userInput="{{simpleProduct.price}}" selector="{{AdminProductFormSection.productPrice}}" stepKey="assertFieldPrice"/> + <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="openSeoSectionAssert"/> + <seeInField userInput="{{simpleProduct.urlKey}}" selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="assertFieldUrlKey"/> + </actionGroup> + <!--Assert text in Related, Up-Sell or Cross-Sell section in Admin Product page--> <actionGroup name="AssertTextInAdminProductRelatedUpSellCrossSellSection"> <arguments> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/StorefrontProductPageActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/StorefrontProductPageActionGroup.xml index 0644cdf3cc07c..4923b1d969b3b 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/StorefrontProductPageActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/StorefrontProductPageActionGroup.xml @@ -21,4 +21,21 @@ <waitForPageLoad stepKey="waitForPageLoad"/> <see selector="{{StorefrontMessagesSection.success}}" userInput="You added {{productName}} to your shopping cart." stepKey="seeAddToCartSuccessMessage"/> </actionGroup> + + <!--Verify text length validation hint with multiple inputs--> + <actionGroup name="testDynamicValidationHint"> + <arguments> + <argument name="charLimit"/> + </arguments> + <fillField userInput="abcde" selector="{{StorefrontProductPageSection.customTextOptionInput}}" stepKey="textInput1"/> + <see selector="{{StorefrontProductPageSection.charCounter}}" userInput="(15 remaining)" stepKey="assertHint1"/> + <fillField userInput="abcdefghjklansdmnbv" selector="{{StorefrontProductPageSection.customTextOptionInput}}" stepKey="textInput2"/> + <see selector="{{StorefrontProductPageSection.charCounter}}" userInput="(1 remaining)" stepKey="assertHint2"/> + <fillField userInput="abcdefghjklansdmnbvd" selector="{{StorefrontProductPageSection.customTextOptionInput}}" stepKey="textInput3"/> + <see selector="{{StorefrontProductPageSection.charCounter}}" userInput="(0 remaining)" stepKey="assertHint3"/> + <fillField userInput="abcdefghjklansdmnbvds" selector="{{StorefrontProductPageSection.customTextOptionInput}}" stepKey="textInput4"/> + <see selector="{{StorefrontProductPageSection.charCounter}}" userInput="(1 too many)" stepKey="assertHint4"/> + <fillField userInput="abcdefghjklansdmnbvdsasdfghjmn" selector="{{StorefrontProductPageSection.customTextOptionInput}}" stepKey="textInput5"/> + <see selector="{{StorefrontProductPageSection.charCounter}}" userInput="(10 too many)" stepKey="assertHint5"/> + </actionGroup> </actionGroups> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductCustomizableOptionsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductCustomizableOptionsSection.xml index 703ba081e3123..702de0a8e1803 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductCustomizableOptionsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductCustomizableOptionsSection.xml @@ -15,6 +15,12 @@ <element name="useDefaultOptionTitleByIndex" type="text" selector="[data-index='options'] [data-index='values'] tr[data-repeat-index='{{var1}}'] [name^='options_use_default']" parameterized="true"/> <element name="addOptionBtn" type="button" selector="button[data-index='button_add']"/> <element name="fillOptionTitle" type="input" selector="//span[text()='{{var1}}']/parent::div/parent::div/parent::div//span[text()='Option Title']/parent::label/parent::div//input[@class='admin__control-text']" parameterized="true"/> + <element name="optionTitleInput" type="input" selector="input[name='product[options][0][title]']"/> + <element name="optionTypeOpenDropDown" type="button" selector=".admin__dynamic-rows[data-index='options'] .action-select"/> + <element name="optionTypeTextField" type="button" selector=".admin__dynamic-rows[data-index='options'] .action-menu._active li li"/> + <element name="maxCharactersInput" type="input" selector="input[name='product[options][0][max_characters]']"/> + + <element name="checkSelect" type="select" selector="//span[text()='{{var1}}']/parent::div/parent::div/parent::div//span[text()='Option Type']/parent::label/parent::div//div[@data-role='selected-option']" parameterized="true"/> <element name="checkDropDown" type="select" selector="//span[text()='{{var1}}']/parent::div/parent::div/parent::div//parent::label/parent::div//li[@class='admin__action-multiselect-menu-inner-item']//label[text()='Drop-down']" parameterized="true"/> <element name="clickAddValue" type="button" selector="//span[text()='{{var1}}']/parent::div/parent::div/parent::div//tfoot//button" parameterized="true"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontProductPageSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontProductPageSection.xml index 8e902b111fca8..a3703839601fd 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontProductPageSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontProductPageSection.xml @@ -13,5 +13,7 @@ <element name="addToCartBtn" type="button" selector="button.action.tocart.primary"/> <element name="successMsg" type="button" selector="div.message-success"/> <element name="addToWishlist" type="button" selector="//a[@class='action towishlist']" timeout="30"/> + <element name="customTextOptionInput" type="input" selector=".input-text.product-custom-option"/> + <element name="charCounter" type="text" selector=".character-counter"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/ConfigurableOptionTextInputLengthValidationHint.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/ConfigurableOptionTextInputLengthValidationHint.xml new file mode 100644 index 0000000000000..d5fc5dfd8ed20 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/ConfigurableOptionTextInputLengthValidationHint.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="ConfigurableOptionTextinputLengthValidationHintTest"> + <annotations> + <features value="Product Customizable Option"/> + <stories value="Customizable text option input-length validation hint changes dynamically"/> + <title value="You should have a dynamic length validation hint when using text option has max char limit"/> + <description value="You should have a dynamic length validation hint when using text option has max char limit"/> + <severity value="MINOR"/> + <testCaseId value="MAGETWO-92229"/> + <group value="product123"/> + </annotations> + <before> + <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + </before> + <after> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + </after> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> + <actionGroup ref="AdminCreateSimpleProductWithTextOptionCharLimit" stepKey="fillProductFieldsInAdmin"> + <argument name="category" value="$$createPreReqCategory$$"/> + <argument name="simpleProduct" value="_defaultProduct"/> + <argument name="charLimit" value="20"/> + </actionGroup> + <actionGroup ref="AssertProductInStorefrontCategoryPage" stepKey="assertProductInStorefront1"> + <argument name="category" value="$$createPreReqCategory$$"/> + <argument name="product" value="_defaultProduct"/> + </actionGroup> + <actionGroup ref="AssertProductInStorefrontProductPage" stepKey="assertProductInStorefront2"> + <argument name="product" value="_defaultProduct"/> + </actionGroup> + <actionGroup ref="testDynamicValidationHint" stepKey="testDynamicValidationHint1"> + <argument name="charLimit" value="20"/> + </actionGroup> + </test> +</tests> From f89061da5740635086f6b963a2a74de6d06db8a1 Mon Sep 17 00:00:00 2001 From: RyanZolper <zolper11@gmail.com> Date: Tue, 29 May 2018 13:28:06 -0500 Subject: [PATCH 0848/2023] fixed dev group value --- .../Test/ConfigurableOptionTextInputLengthValidationHint.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/ConfigurableOptionTextInputLengthValidationHint.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/ConfigurableOptionTextInputLengthValidationHint.xml index d5fc5dfd8ed20..45db40dd2e3dd 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/ConfigurableOptionTextInputLengthValidationHint.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/ConfigurableOptionTextInputLengthValidationHint.xml @@ -16,7 +16,7 @@ <description value="You should have a dynamic length validation hint when using text option has max char limit"/> <severity value="MINOR"/> <testCaseId value="MAGETWO-92229"/> - <group value="product123"/> + <group value="product"/> </annotations> <before> <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> From 093f1b9f8e900b1272d4528d2274312c4006b7d6 Mon Sep 17 00:00:00 2001 From: Alex Paliarush <apaliarush@magento.com> Date: Tue, 29 May 2018 18:29:43 -0500 Subject: [PATCH 0849/2023] ENGCOM-1663: Include 'products' in category query #48 - Fixed test in case when indexer mode is 'on schedule' --- .../Magento/GraphQl/Catalog/CategoryTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php index 8fa731fb0d7f2..8fc19a21421c0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php @@ -120,6 +120,18 @@ public function testCategoriesTree() */ public function testCategoryProducts() { + /** @var \Magento\Catalog\Model\Indexer\Category\Product\Processor $categoryProductIndexer */ + $categoryProductIndexer = $this->objectManager->get( + \Magento\Catalog\Model\Indexer\Category\Product\Processor::class + ); + $categoryProductIndexer->reindexAll(); + + /** @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor $inventoryIndexer */ + $inventoryIndexer = $this->objectManager->get( + \Magento\CatalogInventory\Model\Indexer\Stock\Processor::class + ); + $inventoryIndexer->reindexAll(); + $categoryId = 4; $query = <<<QUERY { From a65e2418a54f1e65a0617b3c9a4c0557e9203406 Mon Sep 17 00:00:00 2001 From: Max Chadwick <mpchadwick@gmail.com> Date: Tue, 29 May 2018 22:51:53 -0400 Subject: [PATCH 0850/2023] Use the timeout when querying Elasticsearch --- app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php b/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php index f428bbf961e3b..b6ec06d48a487 100644 --- a/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php +++ b/app/code/Magento/Elasticsearch/Model/Client/Elasticsearch.php @@ -293,7 +293,8 @@ public function deleteMapping($index, $entityType) */ public function query($query) { - return $this->client->search($query); + $params = array_merge($query, ['client' => ['timeout' => $this->clientOptions['timeout']]]); + return $this->client->search($params); } /** From 909c430c615b962b0393f7e98ae33fba11c09194 Mon Sep 17 00:00:00 2001 From: Alex Paliarush <apaliarush@magento.com> Date: Tue, 29 May 2018 23:43:56 -0500 Subject: [PATCH 0851/2023] MAGETWO-92260: GraphQL - Fix urlResolver query to support relative path #13 - Fixed and added tests - Resolved incorrect dependencies between modules and introduced extension point for custom URL resolver --- .../UrlRewrite/HomePageUrlResolver.php | 47 ++++++++++++ .../Magento/CmsUrlRewriteGraphQl/etc/di.xml | 16 +++++ .../Model/Resolver/UrlRewrite.php | 23 +++--- .../Resolver/UrlRewrite/CustomUrlResolver.php | 41 +++++++++++ .../UrlRewrite/CustomUrlResolverInterface.php | 24 +++++++ .../Magento/UrlRewriteGraphQl/composer.json | 5 +- app/code/Magento/UrlRewriteGraphQl/etc/di.xml | 10 +++ .../GraphQl/UrlRewrite/UrlResolverTest.php | 71 +++++++++++++------ 8 files changed, 197 insertions(+), 40 deletions(-) create mode 100644 app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlResolver.php create mode 100644 app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml create mode 100644 app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolver.php create mode 100644 app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolverInterface.php create mode 100644 app/code/Magento/UrlRewriteGraphQl/etc/di.xml diff --git a/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlResolver.php b/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlResolver.php new file mode 100644 index 0000000000000..d20323a485d71 --- /dev/null +++ b/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlResolver.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CmsUrlRewriteGraphQl\Model\Resolver\UrlRewrite; + +use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolverInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Cms\Helper\Page; + +/** + * Home page URL resolver. + */ +class HomePageUrlResolver implements CustomUrlResolverInterface +{ + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface + */ + private $scopeConfig; + + /** + * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + */ + public function __construct( + \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + ) { + $this->scopeConfig = $scopeConfig; + } + + /** + * @inheritdoc + */ + public function resolveUrl($urlKey): ?string + { + if ($urlKey === '/') { + $homePageUrl = $this->scopeConfig->getValue( + Page::XML_PATH_HOME_PAGE, + ScopeInterface::SCOPE_STORE + ); + return $homePageUrl; + } + return null; + } +} diff --git a/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml b/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml new file mode 100644 index 0000000000000..8cd226b3fd258 --- /dev/null +++ b/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolver"> + <arguments> + <argument name="urlResolvers" xsi:type="array"> + <item name="homePageResolver" xsi:type="object">Magento\CmsUrlRewriteGraphQl\Model\Resolver\UrlRewrite\HomePageUrlResolver</item> + </argument> + </arguments> + </type> +</config> diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php index 8ec3874d9095b..0de21c81f7a8c 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php @@ -14,8 +14,7 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\UrlRewrite\Model\UrlFinderInterface; -use Magento\Store\Model\ScopeInterface; -use Magento\Cms\Helper\Page; +use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolverInterface; /** * UrlRewrite field resolver, used for GraphQL request processing. @@ -38,26 +37,26 @@ class UrlRewrite implements ResolverInterface private $valueFactory; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var UrlRewrite\CustomUrlResolverInterface */ - private $scopeConfig; - + private $customUrlResolver; + /** * @param UrlFinderInterface $urlFinder * @param StoreManagerInterface $storeManager * @param ValueFactory $valueFactory - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param CustomUrlResolverInterface $customUrlResolver */ public function __construct( UrlFinderInterface $urlFinder, StoreManagerInterface $storeManager, ValueFactory $valueFactory, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + CustomUrlResolverInterface $customUrlResolver ) { $this->urlFinder = $urlFinder; $this->storeManager = $storeManager; $this->valueFactory = $valueFactory; - $this->scopeConfig = $scopeConfig; + $this->customUrlResolver = $customUrlResolver; } /** @@ -78,13 +77,9 @@ public function resolve( $url = $args['url']; if (substr($url, 0, 1) === '/' && $url !== '/') { $url = ltrim($url, '/'); - } else if ($url === '/') { - $homePageIdentifier = $this->scopeConfig->getValue( - Page::XML_PATH_HOME_PAGE, - ScopeInterface::SCOPE_STORE - ); - $url = $homePageIdentifier; } + $customUrl = $this->customUrlResolver->resolveUrl($url); + $url = $customUrl ?: $url; $urlRewrite = $this->findCanonicalUrl($url); if ($urlRewrite) { $urlRewriteReturnArray = [ diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolver.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolver.php new file mode 100644 index 0000000000000..08efb54bd6bbb --- /dev/null +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolver.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite; + +/** + * Pool of custom URL resolvers. + */ +class CustomUrlResolver implements CustomUrlResolverInterface +{ + /** + * @var CustomUrlResolverInterface[] + */ + private $urlResolvers; + + /** + * @param CustomUrlResolverInterface[] $urlResolvers + */ + public function __construct(array $urlResolvers = []) + { + $this->urlResolvers = $urlResolvers; + } + + /** + * @inheritdoc + */ + public function resolveUrl($urlKey): ?string + { + foreach ($this->urlResolvers as $urlResolver) { + $url = $urlResolver->resolveUrl($urlKey); + if ($url !== null) { + return $url; + } + } + return null; + } +} diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolverInterface.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolverInterface.php new file mode 100644 index 0000000000000..1aee63b670635 --- /dev/null +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolverInterface.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite; + +/** + * Interface for resolution of custom URLs. + * + * It can be used, for example, to resolve '\' URL path to a 'Home' page. + */ +interface CustomUrlResolverInterface +{ + /** + * Resolve URL based on custom rules. + * + * @param string $urlKey + * @return string|null Return null if URL cannot be resolved + */ + public function resolveUrl($urlKey): ?string; +} diff --git a/app/code/Magento/UrlRewriteGraphQl/composer.json b/app/code/Magento/UrlRewriteGraphQl/composer.json index a1db660ab1526..8d5295a2389fa 100644 --- a/app/code/Magento/UrlRewriteGraphQl/composer.json +++ b/app/code/Magento/UrlRewriteGraphQl/composer.json @@ -6,8 +6,7 @@ "php" : "~7.1.3||~7.2.0", "magento/framework" : "*", "magento/module-url-rewrite" : "*", - "magento/module-store" : "*", - "magento/cms" : "*" + "magento/module-store": "*" }, "suggest" : { "magento/module-graph-ql" : "*" @@ -24,4 +23,4 @@ "Magento\\UrlRewriteGraphQl\\" : "" } } -} \ No newline at end of file +} diff --git a/app/code/Magento/UrlRewriteGraphQl/etc/di.xml b/app/code/Magento/UrlRewriteGraphQl/etc/di.xml new file mode 100644 index 0000000000000..c7b1533962af0 --- /dev/null +++ b/app/code/Magento/UrlRewriteGraphQl/etc/di.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <preference for="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolverInterface" type="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolver"/> +</config> diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php index 4b6e00ba5cf74..0bd24ee7bc88c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php @@ -39,13 +39,13 @@ public function testProductUrlResolver() /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); $product = $productRepository->get($productSku, false, null, true); - $storeId = $product->getStoreId(); + $storeId = $product->getStoreId(); /** @var UrlFinderInterface $urlFinder */ $urlFinder = $this->objectManager->get(UrlFinderInterface::class); $actualUrls = $urlFinder->findOneByData( [ - 'request_path' =>$urlPath, + 'request_path' => $urlPath, 'store_id' => $storeId ] ); @@ -81,14 +81,14 @@ public function testProductUrlWithCanonicalUrlInput() /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); $product = $productRepository->get($productSku, false, null, true); - $storeId = $product->getStoreId(); + $storeId = $product->getStoreId(); $product->getUrlKey(); /** @var UrlFinderInterface $urlFinder */ $urlFinder = $this->objectManager->get(UrlFinderInterface::class); $actualUrls = $urlFinder->findOneByData( [ - 'request_path' =>$urlPath, + 'request_path' => $urlPath, 'store_id' => $storeId ] ); @@ -125,13 +125,13 @@ public function testCategoryUrlResolver() /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); $product = $productRepository->get($productSku, false, null, true); - $storeId = $product->getStoreId(); + $storeId = $product->getStoreId(); /** @var UrlFinderInterface $urlFinder */ $urlFinder = $this->objectManager->get(UrlFinderInterface::class); $actualUrls = $urlFinder->findOneByData( [ - 'request_path' =>$urlPath2, + 'request_path' => $urlPath2, 'store_id' => $storeId ] ); @@ -146,7 +146,7 @@ public function testCategoryUrlResolver() id canonical_url type - } + } } QUERY; $response = $this->graphQlQuery($query); @@ -178,7 +178,7 @@ public function testCMSPageUrlResolver() = <<<QUERY { urlResolver(url:"{$requestPath}") - { + { id canonical_url type @@ -202,16 +202,16 @@ public function testProductUrlRewriteResolver() /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); $product = $productRepository->get($productSku, false, null, true); - $storeId = $product->getStoreId(); + $storeId = $product->getStoreId(); $product->setUrlKey('p002-new')->save(); - $urlPath = $product->getUrlKey() .'.html'; + $urlPath = $product->getUrlKey() . '.html'; $this->assertEquals($urlPath, 'p002-new.html'); /** @var UrlFinderInterface $urlFinder */ $urlFinder = $this->objectManager->get(UrlFinderInterface::class); $actualUrls = $urlFinder->findOneByData( [ - 'request_path' =>$urlPath, + 'request_path' => $urlPath, 'store_id' => $storeId ] ); @@ -225,7 +225,7 @@ public function testProductUrlRewriteResolver() id canonical_url type - } + } } QUERY; $response = $this->graphQlQuery($query); @@ -247,13 +247,13 @@ public function testInvalidUrlResolverInput() /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); $product = $productRepository->get($productSku, false, null, true); - $storeId = $product->getStoreId(); + $storeId = $product->getStoreId(); /** @var UrlFinderInterface $urlFinder */ $urlFinder = $this->objectManager->get(UrlFinderInterface::class); $urlFinder->findOneByData( [ - 'request_path' =>$urlPath, + 'request_path' => $urlPath, 'store_id' => $storeId ] ); @@ -272,35 +272,36 @@ public function testInvalidUrlResolverInput() $this->assertArrayHasKey('urlResolver', $response); $this->assertNull($response['urlResolver']); } - + /** * Test for category entity with leading slash + * + * @magentoApiDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php */ public function testCategoryUrlWithLeadingSlash() { $productSku = 'p002'; - $urlPath2 = 'cat-1.html'; + $urlPath = 'cat-1.html'; /** @var ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); $product = $productRepository->get($productSku, false, null, true); - $storeId = $product->getStoreId(); - + $storeId = $product->getStoreId(); + /** @var UrlFinderInterface $urlFinder */ $urlFinder = $this->objectManager->get(UrlFinderInterface::class); $actualUrls = $urlFinder->findOneByData( [ - 'request_path' => $urlPath2, + 'request_path' => $urlPath, 'store_id' => $storeId ] ); $categoryId = $actualUrls->getEntityId(); $targetPath = $actualUrls->getTargetPath(); $expectedType = $actualUrls->getEntityType(); - - $query - = <<<QUERY + + $query = <<<QUERY { - urlResolver(url:"/{$urlPath2}") + urlResolver(url:"/{$urlPath}") { id canonical_url @@ -314,4 +315,28 @@ public function testCategoryUrlWithLeadingSlash() $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']); $this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']); } + + /** + * Test resolution of '/' path to home page + */ + public function testResolveSlash() + { + $query + = <<<QUERY +{ + urlResolver(url:"/") + { + id + canonical_url + type + } +} +QUERY; + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('urlResolver', $response); + $this->assertEquals(2, $response['urlResolver']['id']); + $this->assertEquals('cms/page/view/page_id/2', $response['urlResolver']['canonical_url']); + $this->assertEquals('CMS_PAGE', $response['urlResolver']['type']); + } } From aca9103445f3d260fc9dae178f91e60f7794d405 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Wed, 30 May 2018 08:07:06 +0300 Subject: [PATCH 0852/2023] ENGCOM-1702: [Forwardport] Moved css from media #TODO #15536 --- .../luma/Magento_Theme/web/css/source/_module.less | 5 ++++- .../Magento/Sniffs/Less/PropertiesSortingSniff.php | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less index 94f34cd0cf1e1..83157281561c2 100644 --- a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less @@ -332,7 +332,10 @@ .widget.block { .lib-css(margin, @indent__base 0); } - .links .widget.block { margin: 0; } + + .links .widget.block { + margin: 0; + } } .no-display:extend(.abs-no-display all) { diff --git a/dev/tests/static/framework/Magento/Sniffs/Less/PropertiesSortingSniff.php b/dev/tests/static/framework/Magento/Sniffs/Less/PropertiesSortingSniff.php index 29b6d9a8cae9d..5f8953da5cf9f 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Less/PropertiesSortingSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Less/PropertiesSortingSniff.php @@ -100,6 +100,14 @@ public function process(File $phpcsFile, $stackPtr) */ private function validatePropertiesSorting(File $phpcsFile, $stackPtr, array $properties) { + // Fix needed for cases when incorrect properties passed for validation due to bug in PHP tokens. + $symbolsForSkip = ['(', 'block']; + $properties = array_filter( + $properties, + function ($var) use ($symbolsForSkip) { + return !in_array($var, $symbolsForSkip); + } + ); $originalProperties = $properties; sort($properties); From cccfe04d0f2dec820c09a6562ffdf5abe9061159 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Fri, 25 May 2018 11:48:45 +0200 Subject: [PATCH 0853/2023] fix dynamical assigned property as it wasn't assigned to an existing one --- app/code/Magento/Webapi/Model/Soap/Fault.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Webapi/Model/Soap/Fault.php b/app/code/Magento/Webapi/Model/Soap/Fault.php index b8ddf4e47d451..74b1b41ee1bf5 100644 --- a/app/code/Magento/Webapi/Model/Soap/Fault.php +++ b/app/code/Magento/Webapi/Model/Soap/Fault.php @@ -39,7 +39,9 @@ class Fault const NODE_DETAIL_WRAPPER = 'GenericFault'; /**#@-*/ - /**#@-*/ + /** + * @var string + */ protected $_soapFaultCode; /** @@ -114,7 +116,7 @@ public function __construct( \Magento\Framework\Locale\ResolverInterface $localeResolver, State $appState ) { - $this->_soapCode = $exception->getOriginator(); + $this->_soapFaultCode = $exception->getOriginator(); $this->_parameters = $exception->getDetails(); $this->_wrappedErrors = $exception->getErrors(); $this->stackTrace = $exception->getStackTrace() ?: $exception->getTraceAsString(); @@ -194,7 +196,7 @@ public function getDetails() */ public function getSoapCode() { - return $this->_soapCode; + return $this->_soapFaultCode; } /** From 6f4e81b6ec8d685d2fdfbd65b7b64939b533fb45 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Wed, 30 May 2018 10:25:47 +0300 Subject: [PATCH 0854/2023] MAGETWO-90762: [2.3.0] Placing an order takes more time then usual --- .../GuestPaymentInformationManagement.php | 32 ++++++- .../GuestPaymentInformationManagementTest.php | 90 +++++++++++++++---- .../Quote/Model/PaymentMethodManagement.php | 24 ++--- .../Model/PaymentMethodManagementTest.php | 36 ++++---- 4 files changed, 131 insertions(+), 51 deletions(-) diff --git a/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php index a17cf41585649..333226b7d216f 100644 --- a/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php +++ b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Checkout\Model; @@ -10,6 +11,7 @@ use Magento\Framework\App\ResourceConnection; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Quote\Model\Quote; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -135,13 +137,19 @@ public function savePaymentInformation( \Magento\Quote\Api\Data\PaymentInterface $paymentMethod, \Magento\Quote\Api\Data\AddressInterface $billingAddress = null ) { + $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id'); + /** @var Quote $quote */ + $quote = $this->cartRepository->getActive($quoteIdMask->getQuoteId()); + if ($billingAddress) { $billingAddress->setEmail($email); - $this->billingAddressManagement->assign($cartId, $billingAddress); + $quote->removeAddress($quote->getBillingAddress()->getId()); + $quote->setBillingAddress($billingAddress); + $quote->setDataChanges(true); } else { - $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id'); - $this->cartRepository->getActive($quoteIdMask->getQuoteId())->getBillingAddress()->setEmail($email); + $quote->getBillingAddress()->setEmail($email); } + $this->limitShippingCarrier($quote); $this->paymentMethodManagement->set($cartId, $paymentMethod); return true; @@ -169,4 +177,22 @@ private function getLogger() } return $this->logger; } + + /** + * Limits shipping rates request by carrier from shipping address. + * + * @param Quote $quote + * + * @return void + * @see \Magento\Shipping\Model\Shipping::collectRates + */ + private function limitShippingCarrier(Quote $quote) : void + { + $shippingAddress = $quote->getShippingAddress(); + if ($shippingAddress && $shippingAddress->getShippingMethod()) { + $shippingDataArray = explode('_', $shippingAddress->getShippingMethod()); + $shippingCarrier = array_shift($shippingDataArray); + $shippingAddress->setLimitCarrier($shippingCarrier); + } + } } diff --git a/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php index da0de5d4f0a3d..c4924ca211024 100644 --- a/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php @@ -3,11 +3,15 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Checkout\Test\Unit\Model; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\QuoteIdMask; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -96,6 +100,7 @@ public function testSavePaymentInformationAndPlaceOrder() $email = 'email@magento.com'; $paymentMock = $this->createMock(\Magento\Quote\Api\Data\PaymentInterface::class); $billingAddressMock = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); + $this->getMockForAssignBillingAddress($cartId, $billingAddressMock); $billingAddressMock->expects($this->once())->method('setEmail')->with($email)->willReturnSelf(); @@ -119,10 +124,6 @@ public function testSavePaymentInformationAndPlaceOrder() ->willReturn($adapterMockForCheckout); $adapterMockForCheckout->expects($this->once())->method('beginTransaction'); $adapterMockForCheckout->expects($this->once())->method('commit'); - - $this->billingAddressManagementMock->expects($this->once()) - ->method('assign') - ->with($cartId, $billingAddressMock); $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock); $this->cartManagementMock->expects($this->once())->method('placeOrder')->with($cartId)->willReturn($orderId); @@ -142,6 +143,7 @@ public function testSavePaymentInformationAndPlaceOrderException() $paymentMock = $this->createMock(\Magento\Quote\Api\Data\PaymentInterface::class); $billingAddressMock = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); + $this->getMockForAssignBillingAddress($cartId, $billingAddressMock); $billingAddressMock->expects($this->once())->method('setEmail')->with($email)->willReturnSelf(); $adapterMockForSales = $this->getMockBuilder(AdapterInterface::class) @@ -164,10 +166,7 @@ public function testSavePaymentInformationAndPlaceOrderException() ->willReturn($adapterMockForCheckout); $adapterMockForCheckout->expects($this->once())->method('beginTransaction'); $adapterMockForCheckout->expects($this->once())->method('rollback'); - - $this->billingAddressManagementMock->expects($this->once()) - ->method('assign') - ->with($cartId, $billingAddressMock); + $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock); $exception = new \Exception(__('DB exception')); $this->cartManagementMock->expects($this->once())->method('placeOrder')->willThrowException($exception); @@ -185,11 +184,9 @@ public function testSavePaymentInformation() $email = 'email@magento.com'; $paymentMock = $this->createMock(\Magento\Quote\Api\Data\PaymentInterface::class); $billingAddressMock = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); + $this->getMockForAssignBillingAddress($cartId, $billingAddressMock); $billingAddressMock->expects($this->once())->method('setEmail')->with($email)->willReturnSelf(); - $this->billingAddressManagementMock->expects($this->once()) - ->method('assign') - ->with($cartId, $billingAddressMock); $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock); $this->assertTrue($this->model->savePaymentInformation($cartId, $email, $paymentMock, $billingAddressMock)); @@ -201,13 +198,13 @@ public function testSavePaymentInformationWithoutBillingAddress() $email = 'email@magento.com'; $paymentMock = $this->createMock(\Magento\Quote\Api\Data\PaymentInterface::class); $billingAddressMock = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); - $quoteMock = $this->createMock(\Magento\Quote\Model\Quote::class); + $quoteMock = $this->createMock(Quote::class); $billingAddressMock->expects($this->once())->method('setEmail')->with($email)->willReturnSelf(); $this->billingAddressManagementMock->expects($this->never())->method('assign'); $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock); - $quoteIdMaskMock = $this->createPartialMock(\Magento\Quote\Model\QuoteIdMask::class, ['getQuoteId', 'load']); + $quoteIdMaskMock = $this->createPartialMock(QuoteIdMask::class, ['getQuoteId', 'load']); $this->quoteIdMaskFactoryMock->expects($this->once())->method('create')->willReturn($quoteIdMaskMock); $quoteIdMaskMock->expects($this->once())->method('load')->with($cartId, 'masked_id')->willReturnSelf(); $quoteIdMaskMock->expects($this->once())->method('getQuoteId')->willReturn($cartId); @@ -228,6 +225,15 @@ public function testSavePaymentInformationAndPlaceOrderWithLocalizedException() $paymentMock = $this->createMock(\Magento\Quote\Api\Data\PaymentInterface::class); $billingAddressMock = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); + $quoteMock = $this->createMock(Quote::class); + $quoteMock->method('getBillingAddress')->willReturn($billingAddressMock); + $this->cartRepositoryMock->method('getActive')->with($cartId)->willReturn($quoteMock); + + $quoteIdMask = $this->createPartialMock(QuoteIdMask::class, ['getQuoteId', 'load']); + $this->quoteIdMaskFactoryMock->method('create')->willReturn($quoteIdMask); + $quoteIdMask->method('load')->with($cartId, 'masked_id')->willReturnSelf(); + $quoteIdMask->method('getQuoteId')->willReturn($cartId); + $billingAddressMock->expects($this->once())->method('setEmail')->with($email)->willReturnSelf(); $adapterMockForSales = $this->getMockBuilder(AdapterInterface::class) @@ -250,10 +256,7 @@ public function testSavePaymentInformationAndPlaceOrderWithLocalizedException() ->willReturn($adapterMockForCheckout); $adapterMockForCheckout->expects($this->once())->method('beginTransaction'); $adapterMockForCheckout->expects($this->once())->method('rollback'); - - $this->billingAddressManagementMock->expects($this->once()) - ->method('assign') - ->with($cartId, $billingAddressMock); + $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock); $phrase = new \Magento\Framework\Phrase(__('DB exception')); $exception = new \Magento\Framework\Exception\LocalizedException($phrase); @@ -262,4 +265,57 @@ public function testSavePaymentInformationAndPlaceOrderWithLocalizedException() $this->model->savePaymentInformationAndPlaceOrder($cartId, $email, $paymentMock, $billingAddressMock); } + + /** + * @param int $cartId + * @param \PHPUnit_Framework_MockObject_MockObject $billingAddressMock + * @return void + */ + private function getMockForAssignBillingAddress( + int $cartId, + \PHPUnit_Framework_MockObject_MockObject $billingAddressMock + ) : void { + $quoteIdMask = $this->createPartialMock(QuoteIdMask::class, ['getQuoteId', 'load']); + $this->quoteIdMaskFactoryMock->method('create') + ->willReturn($quoteIdMask); + $quoteIdMask->method('load') + ->with($cartId, 'masked_id') + ->willReturnSelf(); + $quoteIdMask->method('getQuoteId') + ->willReturn($cartId); + + $billingAddressId = 1; + $quote = $this->createMock(Quote::class); + $quoteBillingAddress = $this->createMock(Address::class); + $quoteShippingAddress = $this->createPartialMock( + Address::class, + ['setLimitCarrier', 'getShippingMethod'] + ); + $this->cartRepositoryMock->method('getActive') + ->with($cartId) + ->willReturn($quote); + $quote->expects($this->once()) + ->method('getBillingAddress') + ->willReturn($quoteBillingAddress); + $quote->expects($this->once()) + ->method('getShippingAddress') + ->willReturn($quoteShippingAddress); + $quoteBillingAddress->expects($this->once()) + ->method('getId') + ->willReturn($billingAddressId); + $quote->expects($this->once()) + ->method('removeAddress') + ->with($billingAddressId); + $quote->expects($this->once()) + ->method('setBillingAddress') + ->with($billingAddressMock); + $quote->expects($this->once()) + ->method('setDataChanges') + ->willReturnSelf(); + $quoteShippingAddress->method('getShippingMethod') + ->willReturn('flatrate_flatrate'); + $quoteShippingAddress->expects($this->once()) + ->method('setLimitCarrier') + ->with('flatrate'); + } } diff --git a/app/code/Magento/Quote/Model/PaymentMethodManagement.php b/app/code/Magento/Quote/Model/PaymentMethodManagement.php index 91d8fe4dbcffd..b6e4bcf5ccc8f 100644 --- a/app/code/Magento/Quote/Model/PaymentMethodManagement.php +++ b/app/code/Magento/Quote/Model/PaymentMethodManagement.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Quote\Model; @@ -52,38 +53,37 @@ public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method) { /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->get($cartId); - + $quote->setTotalsCollectedFlag(false); $method->setChecks([ \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_CHECKOUT, \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_COUNTRY, \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_CURRENCY, \Magento\Payment\Model\Method\AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX, ]); - $payment = $quote->getPayment(); - - $data = $method->getData(); - $payment->importData($data); if ($quote->isVirtual()) { - $quote->getBillingAddress()->setPaymentMethod($payment->getMethod()); + $address = $quote->getBillingAddress(); } else { + $address = $quote->getShippingAddress(); // check if shipping address is set - if ($quote->getShippingAddress()->getCountryId() === null) { + if ($address->getCountryId() === null) { throw new InvalidTransitionException( __('The shipping address is missing. Set the address and try again.') ); } - $quote->getShippingAddress()->setPaymentMethod($payment->getMethod()); - } - if (!$quote->isVirtual() && $quote->getShippingAddress()) { - $quote->getShippingAddress()->setCollectShippingRates(true); + $address->setCollectShippingRates(true); } + $paymentData = $method->getData(); + $payment = $quote->getPayment(); + $payment->importData($paymentData); + $address->setPaymentMethod($payment->getMethod()); + if (!$this->zeroTotalValidator->isApplicable($payment->getMethodInstance(), $quote)) { throw new InvalidTransitionException(__('The requested Payment Method is not available.')); } - $quote->setTotalsCollectedFlag(false)->collectTotals()->save(); + $quote->save(); return $quote->getPayment()->getId(); } diff --git a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php index 68b077fcdb965..f18d1fa1b06e5 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Quote\Test\Unit\Model; @@ -152,8 +153,8 @@ public function testSetVirtualProduct() ->with($paymentMethod) ->willReturnSelf(); - $quoteMock->expects($this->exactly(2))->method('getPayment')->willReturn($paymentMock); - $quoteMock->expects($this->exactly(2))->method('isVirtual')->willReturn(true); + $quoteMock->method('getPayment')->willReturn($paymentMock); + $quoteMock->expects($this->once())->method('isVirtual')->willReturn(true); $quoteMock->expects($this->once())->method('getBillingAddress')->willReturn($billingAddressMock); $methodInstance = $this->getMockForAbstractClass(\Magento\Payment\Model\MethodInterface::class); @@ -165,7 +166,6 @@ public function testSetVirtualProduct() ->willReturn(true); $quoteMock->expects($this->once())->method('setTotalsCollectedFlag')->with(false)->willReturnSelf(); - $quoteMock->expects($this->once())->method('collectTotals')->willReturnSelf(); $quoteMock->expects($this->once())->method('save')->willReturnSelf(); $paymentMock->expects($this->once())->method('getId')->willReturn($paymentId); @@ -218,9 +218,9 @@ public function testSetVirtualProductThrowsExceptionIfPaymentMethodNotAvailable( ->with($paymentMethod) ->willReturnSelf(); - $quoteMock->expects($this->once())->method('getPayment')->willReturn($paymentMock); - $quoteMock->expects($this->exactly(2))->method('isVirtual')->willReturn(true); - $quoteMock->expects($this->once())->method('getBillingAddress')->willReturn($billingAddressMock); + $quoteMock->method('getPayment')->willReturn($paymentMock); + $quoteMock->method('isVirtual')->willReturn(true); + $quoteMock->method('getBillingAddress')->willReturn($billingAddressMock); $methodInstance = $this->getMockForAbstractClass(\Magento\Payment\Model\MethodInterface::class); $paymentMock->expects($this->once())->method('getMethodInstance')->willReturn($methodInstance); @@ -268,17 +268,20 @@ public function testSetSimpleProduct() $shippingAddressMock = $this->createPartialMock( \Magento\Quote\Model\Quote\Address::class, - ['getCountryId', 'setPaymentMethod'] + ['getCountryId', 'setPaymentMethod', 'setCollectShippingRates'] ); $shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(100); $shippingAddressMock->expects($this->once()) ->method('setPaymentMethod') ->with($paymentMethod) ->willReturnSelf(); + $shippingAddressMock->expects($this->once()) + ->method('setCollectShippingRates') + ->with(true); - $quoteMock->expects($this->exactly(2))->method('getPayment')->willReturn($paymentMock); - $quoteMock->expects($this->exactly(2))->method('isVirtual')->willReturn(false); - $quoteMock->expects($this->exactly(4))->method('getShippingAddress')->willReturn($shippingAddressMock); + $quoteMock->method('getPayment')->willReturn($paymentMock); + $quoteMock->method('isVirtual')->willReturn(false); + $quoteMock->method('getShippingAddress')->willReturn($shippingAddressMock); $methodInstance = $this->getMockForAbstractClass(\Magento\Payment\Model\MethodInterface::class); $paymentMock->expects($this->once())->method('getMethodInstance')->willReturn($methodInstance); @@ -289,7 +292,6 @@ public function testSetSimpleProduct() ->willReturn(true); $quoteMock->expects($this->once())->method('setTotalsCollectedFlag')->with(false)->willReturnSelf(); - $quoteMock->expects($this->once())->method('collectTotals')->willReturnSelf(); $quoteMock->expects($this->once())->method('save')->willReturnSelf(); $paymentMock->expects($this->once())->method('getId')->willReturn($paymentId); @@ -303,7 +305,6 @@ public function testSetSimpleProduct() public function testSetSimpleProductTrowsExceptionIfShippingAddressNotSet() { $cartId = 100; - $methodData = ['method' => 'data']; $quoteMock = $this->createPartialMock( \Magento\Quote\Model\Quote::class, @@ -311,6 +312,7 @@ public function testSetSimpleProductTrowsExceptionIfShippingAddressNotSet() ); $this->quoteRepositoryMock->expects($this->once())->method('get')->with($cartId)->willReturn($quoteMock); + /** @var \Magento\Quote\Model\Quote\Payment|\PHPUnit_Framework_MockObject_MockObject $methodMock */ $methodMock = $this->createPartialMock(\Magento\Quote\Model\Quote\Payment::class, ['setChecks', 'getData']); $methodMock->expects($this->once()) ->method('setChecks') @@ -321,17 +323,13 @@ public function testSetSimpleProductTrowsExceptionIfShippingAddressNotSet() \Magento\Payment\Model\Method\AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX, ]) ->willReturnSelf(); - $methodMock->expects($this->once())->method('getData')->willReturn($methodData); - - $paymentMock = $this->createPartialMock(\Magento\Quote\Model\Quote\Payment::class, ['importData']); - $paymentMock->expects($this->once())->method('importData')->with($methodData)->willReturnSelf(); + $methodMock->expects($this->never())->method('getData'); $shippingAddressMock = $this->createPartialMock(\Magento\Quote\Model\Quote\Address::class, ['getCountryId']); $shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(null); - $quoteMock->expects($this->once())->method('getPayment')->willReturn($paymentMock); - $quoteMock->expects($this->once())->method('isVirtual')->willReturn(false); - $quoteMock->expects($this->once())->method('getShippingAddress')->willReturn($shippingAddressMock); + $quoteMock->method('isVirtual')->willReturn(false); + $quoteMock->method('getShippingAddress')->willReturn($shippingAddressMock); $this->model->set($cartId, $methodMock); } From 15c920ee03b8d3d0b6a97aede4e0a944c876abd9 Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Wed, 30 May 2018 10:27:04 +0300 Subject: [PATCH 0855/2023] MAGETWO-90349: Template file 'header.html' is not found. --- .../Customer/Model/AccountManagement.php | 2 + .../Test/Unit/Model/AccountManagementTest.php | 101 ++++++++++++++ .../Magento/Email/Model/AbstractTemplate.php | 7 +- .../Magento/Email/Model/Template/Config.php | 25 +++- .../Test/Unit/Model/Template/ConfigTest.php | 14 ++ .../Theme/Model/Design/Config/Validator.php | 1 + .../Test/Unit/Model/Config/ValidatorTest.php | 4 +- .../Model/Design/Config/ValidatorTest.php | 125 ++++++++++++++++++ 8 files changed, 272 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/Theme/Test/Unit/Model/Design/Config/ValidatorTest.php diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 7d0b271b9b137..4fc74fa695829 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -873,6 +873,8 @@ protected function sendEmailConfirmation(CustomerInterface $customer, $redirectU } catch (MailException $e) { // If we are not able to send a new account email, this should be ignored $this->logger->critical($e); + } catch (\UnexpectedValueException $e) { + $this->logger->error($e); } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index cfd1729e4e06e..9e3a16a307923 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1875,4 +1875,105 @@ private function prepareDateTimeFactory() return $dateTime; } + + /** + * @return void + */ + public function testCreateAccountUnexpectedValueException(): void + { + $websiteId = 1; + $storeId = null; + $defaultStoreId = 1; + $customerId = 1; + $customerEmail = 'email@email.com'; + $newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu'; + $exception = new \UnexpectedValueException('Template file was not found'); + + $datetime = $this->prepareDateTimeFactory(); + + $address = $this->createMock(\Magento\Customer\Api\Data\AddressInterface::class); + $address->expects($this->once()) + ->method('setCustomerId') + ->with($customerId); + $store = $this->createMock(\Magento\Store\Model\Store::class); + $store->expects($this->once()) + ->method('getId') + ->willReturn($defaultStoreId); + $website = $this->createMock(\Magento\Store\Model\Website::class); + $website->expects($this->atLeastOnce()) + ->method('getStoreIds') + ->willReturn([1, 2, 3]); + $website->expects($this->once()) + ->method('getDefaultStore') + ->willReturn($store); + $customer = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class); + $customer->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn($customerId); + $customer->expects($this->atLeastOnce()) + ->method('getEmail') + ->willReturn($customerEmail); + $customer->expects($this->atLeastOnce()) + ->method('getWebsiteId') + ->willReturn($websiteId); + $customer->expects($this->atLeastOnce()) + ->method('getStoreId') + ->willReturn($storeId); + $customer->expects($this->once()) + ->method('setStoreId') + ->with($defaultStoreId); + $customer->expects($this->once()) + ->method('getAddresses') + ->willReturn([$address]); + $customer->expects($this->once()) + ->method('setAddresses') + ->with(null); + $this->customerRepository->expects($this->once()) + ->method('get') + ->with($customerEmail) + ->willReturn($customer); + $this->share->expects($this->once()) + ->method('isWebsiteScope') + ->willReturn(true); + $this->storeManager->expects($this->atLeastOnce()) + ->method('getWebsite') + ->with($websiteId) + ->willReturn($website); + $this->customerRepository->expects($this->atLeastOnce()) + ->method('save') + ->willReturn($customer); + $this->addressRepository->expects($this->atLeastOnce()) + ->method('save') + ->with($address); + $this->customerRepository->expects($this->once()) + ->method('getById') + ->with($customerId) + ->willReturn($customer); + $this->random->expects($this->once()) + ->method('getUniqueHash') + ->willReturn($newLinkToken); + $customerSecure = $this->createPartialMock( + \Magento\Customer\Model\Data\CustomerSecure::class, + ['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash'] + ); + $customerSecure->expects($this->any()) + ->method('setRpToken') + ->with($newLinkToken); + $customerSecure->expects($this->any()) + ->method('setRpTokenCreatedAt') + ->with($datetime) + ->willReturnSelf(); + $customerSecure->expects($this->any()) + ->method('getPasswordHash') + ->willReturn(null); + $this->customerRegistry->expects($this->atLeastOnce()) + ->method('retrieveSecureData') + ->willReturn($customerSecure); + $this->emailNotificationMock->expects($this->once()) + ->method('newAccount') + ->willThrowException($exception); + $this->logger->expects($this->once())->method('error')->with($exception); + + $this->accountManagement->createAccount($customer); + } } diff --git a/app/code/Magento/Email/Model/AbstractTemplate.php b/app/code/Magento/Email/Model/AbstractTemplate.php index 4830ecfbb74b3..a6ecdaf24ebbb 100644 --- a/app/code/Magento/Email/Model/AbstractTemplate.php +++ b/app/code/Magento/Email/Model/AbstractTemplate.php @@ -531,14 +531,13 @@ protected function cancelDesignConfig() * * @param string $templateId * @return $this - * @throws \Magento\Framework\Exception\MailException */ public function setForcedArea($templateId) { - if ($this->area) { - throw new \LogicException(__('The area is already set.')); + if ($this->area === null) { + $this->area = $this->emailConfig->getTemplateArea($templateId); } - $this->area = $this->emailConfig->getTemplateArea($templateId); + return $this; } diff --git a/app/code/Magento/Email/Model/Template/Config.php b/app/code/Magento/Email/Model/Template/Config.php index bdd9054e7969b..d10c394dcb715 100644 --- a/app/code/Magento/Email/Model/Template/Config.php +++ b/app/code/Magento/Email/Model/Template/Config.php @@ -205,8 +205,9 @@ public function getTemplateFilename($templateId, $designParams = []) $designParams['module'] = $module; $file = $this->_getInfo($templateId, 'file'); + $filename = $this->getFilename($file, $designParams, $module); - return $this->viewFileSystem->getEmailTemplateFileName($file, $designParams, $module); + return $filename; } /** @@ -230,4 +231,26 @@ protected function _getInfo($templateId, $fieldName) } return $data[$templateId][$fieldName]; } + + /** + * Retrieve template file path. + * + * @param string $file + * @param array $designParams + * @param string $module + * + * @return string + * + * @throws \UnexpectedValueException + */ + private function getFilename(string $file, array $designParams, string $module): string + { + $filename = $this->viewFileSystem->getEmailTemplateFileName($file, $designParams, $module); + + if ($filename === false) { + throw new \UnexpectedValueException("Template file '{$file}' is not found."); + } + + return $filename; + } } diff --git a/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php b/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php index 47c3ac1e7e450..b396f2ede8977 100644 --- a/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php @@ -272,6 +272,20 @@ public function testGetTemplateFilenameWithNoParams() $this->assertEquals('_files/Fixture/ModuleOne/view/frontend/email/one.html', $actualResult); } + /** + * @expectedException \UnexpectedValueException + * @expectedExceptionMessage Template file 'one.html' is not found + * @return void + */ + public function testGetTemplateFilenameWrongFileName(): void + { + $this->viewFileSystem->expects($this->once())->method('getEmailTemplateFileName') + ->with('one.html', $this->designParams, 'Fixture_ModuleOne') + ->willReturn(false); + + $this->model->getTemplateFilename('template_one', $this->designParams); + } + /** * @param string $getterMethod * @param $argument diff --git a/app/code/Magento/Theme/Model/Design/Config/Validator.php b/app/code/Magento/Theme/Model/Design/Config/Validator.php index 9fed5be6201b4..994eeba317a34 100644 --- a/app/code/Magento/Theme/Model/Design/Config/Validator.php +++ b/app/code/Magento/Theme/Model/Design/Config/Validator.php @@ -114,6 +114,7 @@ private function getTemplateText($templateId, DesignConfigInterface $designConfi if (is_numeric($templateId)) { $template->load($templateId); } else { + $template->setForcedArea($templateId); $template->loadDefault($templateId); } $text = $template->getTemplateText(); diff --git a/app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php b/app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php index 4a1a1982ea653..3b337312e3fb5 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php @@ -70,7 +70,7 @@ public function testValidateHasRecursiveReference() $designElementMock->expects($this->once())->method('getValue')->willReturn($fieldConfig['field']); $templateMock = $this->getMockBuilder(\Magento\Email\Model\TemplateInterface::class) - ->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign']) + ->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign', 'setForcedArea']) ->getMock(); $this->templateFactoryMock->expects($this->once())->method('create')->willReturn($templateMock); @@ -115,7 +115,7 @@ public function testValidateNoRecursiveReference() $designElementMock->expects($this->once())->method('getValue')->willReturn($fieldConfig['field']); $templateMock = $this->getMockBuilder(\Magento\Email\Model\TemplateInterface::class) - ->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign']) + ->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign', 'setForcedArea']) ->getMock(); $this->templateFactoryMock->expects($this->once())->method('create')->willReturn($templateMock); diff --git a/app/code/Magento/Theme/Test/Unit/Model/Design/Config/ValidatorTest.php b/app/code/Magento/Theme/Test/Unit/Model/Design/Config/ValidatorTest.php new file mode 100644 index 0000000000000..6b26235d0efcc --- /dev/null +++ b/app/code/Magento/Theme/Test/Unit/Model/Design/Config/ValidatorTest.php @@ -0,0 +1,125 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Theme\Test\Unit\Model\Design\Config; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Theme\Model\Design\Config\Validator; + +/** + * Unit tests for Magento\Theme\Test\Unit\Model\Design\Config\Validator. + */ +class ValidatorTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Framework\Mail\TemplateInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $templateFactory; + + /** + * @var \Magento\Framework\Mail\TemplateInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $template; + + /** + * @var \Magento\Theme\Api\Data\DesignConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $designConfig; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->templateFactory = $this->getMockBuilder(\Magento\Framework\Mail\TemplateInterfaceFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->template = $this->getMockBuilder(\Magento\Framework\Mail\TemplateInterface::class) + ->disableOriginalConstructor() + ->setMethods( + [ + 'emulateDesign', + 'setForcedArea', + 'loadDefault', + 'getTemplateText', + 'revertDesign', + ] + ) + ->getMockForAbstractClass(); + $this->templateFactory->expects($this->any())->method('create')->willReturn($this->template); + $this->designConfig = $this->getMockBuilder(\Magento\Theme\Api\Data\DesignConfigInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getExtensionAttributes']) + ->getMockForAbstractClass(); + } + + /** + * @return void + */ + public function testGetDefaultTemplateTextDefaultScope(): void + { + $templateId = 'email_template'; + $designData = [ + 'field_config' => ['field' => 'fieldValue'], + 'value' => $templateId, + ]; + + $this->templateFactory->expects($this->once())->method('create'); + $this->designConfig->expects($this->any())->method('getScope')->willReturn('default'); + $this->template->expects($this->once())->method('emulateDesign'); + $this->template->expects($this->once())->method('setForcedArea')->with($templateId); + $this->template->expects($this->once())->method('loadDefault')->with($templateId); + $this->template->expects($this->once())->method('getTemplateText'); + $this->template->expects($this->once())->method('revertDesign'); + + $extensionAttributes = $this->getMockBuilder(\Magento\Theme\Api\Data\DesignConfigExtensionInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getDesignConfigData']) + ->getMockForAbstractClass(); + + $extensionAttributes->expects($this->any())->method('getDesignConfigData')->willReturn( + [ + $this->getDesignConfigData($designData), + ] + ); + + $this->designConfig->expects($this->any())->method('getExtensionAttributes')->willReturn($extensionAttributes); + + /** @var Validator $validator */ + $validator = $this->objectManager->getObject( + Validator::class, + [ + 'templateFactory' => $this->templateFactory, + 'fields' => ['field' => 'fieldValue'], + ] + ); + $validator->validate($this->designConfig); + } + + /** + * Returns design config data object. + * + * @param array $data + * @return \Magento\Theme\Model\Data\Design\Config\Data + */ + private function getDesignConfigData(array $data = []): \Magento\Theme\Model\Data\Design\Config\Data + { + return $this->objectManager->getObject( + \Magento\Theme\Model\Data\Design\Config\Data::class, + [ + 'data' => $data, + ] + ); + } +} From 39ba713abced7a28f7b40d8a9f5f6a064c3a3a8b Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <fanta1408@gmail.com> Date: Wed, 30 May 2018 10:29:53 +0300 Subject: [PATCH 0856/2023] MAGETWO-90301: Extend MFTF tests to check Checkout Success page --- .../Section/CheckoutShippingMethodsSection.xml | 2 +- .../Checkout/Section/CheckoutShippingSection.xml | 2 +- .../Section/CheckoutSuccessMainSection.xml | 6 +++--- .../Section/CheckoutSuccessRegisterSection.xml | 2 +- .../Checkout/Test/CheckCheckoutSuccessPageTest.xml | 14 ++++---------- 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutShippingMethodsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutShippingMethodsSection.xml index a6e09494b7423..2a59d2bdc8d9b 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutShippingMethodsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutShippingMethodsSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> <section name="CheckoutShippingMethodsSection"> - <element name="next" type="button" selector="button.button.action.continue.primary"/> + <element name="next" type="button" selector="button.button.action.continue.primary" timeout="30"/> <element name="firstShippingMethod" type="radio" selector="//*[@id='checkout-shipping-method-load']//input[@class='radio']"/> <element name="shippingMethodRow" type="text" selector=".form.methods-shipping table tbody tr"/> <element name="checkShippingMethodByName" type="radio" selector="//div[@id='checkout-shipping-method-load']//td[contains(., '{{var1}}')]/..//input" parameterized="true"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutShippingSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutShippingSection.xml index 54fa168a1a4eb..34f32e08d38ca 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutShippingSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutShippingSection.xml @@ -20,7 +20,7 @@ <element name="region" type="select" selector="select[name=region_id]"/> <element name="postcode" type="input" selector="input[name=postcode]"/> <element name="telephone" type="input" selector="input[name=telephone]"/> - <element name="next" type="button" selector="button.button.action.continue.primary"/> + <element name="next" type="button" selector="button.button.action.continue.primary" timeout="30"/> <element name="firstShippingMethod" type="radio" selector="//*[@id='checkout-shipping-method-load']//input[@class='radio']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutSuccessMainSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutSuccessMainSection.xml index 935dfd19903e2..2a1d84d7ccb1f 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutSuccessMainSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutSuccessMainSection.xml @@ -13,9 +13,9 @@ <element name="success" type="text" selector="div.checkout-success"/> <element name="orderNumber" type="text" selector="div.checkout-success > p:nth-child(1) > span"/> <element name="orderNumber22" type="text" selector=".order-number>strong"/> - <element name="orderLink" type="text" selector="a[href*=order_id].order-number"/> + <element name="orderLink" type="text" selector="a[href*=order_id].order-number" timeout="30"/> <element name="orderNumberText" type="text" selector=".checkout-success > p:nth-child(1)"/> - <element name="continueShoppingButton" type="button" selector=".action.primary.continue"/> - <element name="printLink" type="button" selector=".print"/> + <element name="continueShoppingButton" type="button" selector=".action.primary.continue" timeout="30"/> + <element name="printLink" type="button" selector=".print" timeout="30"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutSuccessRegisterSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutSuccessRegisterSection.xml index f3d9d33e156fb..6a7690083ae92 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutSuccessRegisterSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutSuccessRegisterSection.xml @@ -11,6 +11,6 @@ <section name="CheckoutSuccessRegisterSection"> <element name="registerMessage" type="text" selector="#registration p:nth-child(1)"/> <element name="customerEmail" type="text" selector="#registration p:nth-child(2)"/> - <element name="createAccountButton" type="button" selector="#registration form input[type='submit']"/> + <element name="createAccountButton" type="button" selector="#registration form input[type='submit']" timeout="30"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Test/CheckCheckoutSuccessPageTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Test/CheckCheckoutSuccessPageTest.xml index 4b5c45a0d9529..eba21db6ef0d1 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Test/CheckCheckoutSuccessPageTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Test/CheckCheckoutSuccessPageTest.xml @@ -59,13 +59,11 @@ <!--Click Place Order button--> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder"/> - <waitForElement selector="{{CheckoutSuccessMainSection.success}}" time="30" stepKey="waitForLoadSuccessPage"/> <see selector="{{CheckoutSuccessMainSection.successTitle}}" userInput="Thank you for your purchase!" stepKey="seeSuccessTitle"/> <see selector="{{CheckoutSuccessMainSection.orderNumberText}}" userInput="Your order number is: " stepKey="seeOrderNumber"/> <see selector="{{CheckoutSuccessMainSection.success}}" userInput="We'll email you an order confirmation with details and tracking info." stepKey="seeSuccessNotify"/> <click selector="{{CheckoutSuccessMainSection.orderLink}}" stepKey="clickOrderLink"/> - <waitForElement selector="{{StorefrontCustomerOrderViewSection.orderTitle}}" stepKey="waitOrderViewPage"/> <seeInCurrentUrl url="{{StorefrontCustomerOrderPage.url}}" stepKey="seeMyOrderPage"/> <!--Go to product page--> @@ -87,9 +85,8 @@ <!--Click Place Order button--> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder2"/> - <waitForElement selector="{{CheckoutSuccessMainSection.success}}" time="30" stepKey="waitForLoadSuccessPage2"/> + <see selector="{{CheckoutSuccessMainSection.successTitle}}" userInput="Thank you for your purchase!" stepKey="waitForLoadSuccessPage2"/> <click selector="{{CheckoutSuccessMainSection.continueShoppingButton}}" stepKey="clickContinueShoppingButton"/> - <waitForElement selector="{{StorefrontCMSPageSection.mainTitle}}" stepKey="waitHomePage"/> <see userInput="Home Page" selector="{{StorefrontCMSPageSection.mainTitle}}" stepKey="seeHomePageTitle"/> <seeCurrentUrlEquals url="{{_ENV.MAGENTO_BASE_URL}}" stepKey="seeHomePageUrl"/> @@ -112,7 +109,7 @@ <!--Click Place Order button--> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder3"/> - <waitForElement selector="{{CheckoutSuccessMainSection.success}}" time="30" stepKey="waitForLoadSuccessPage3"/> + <see selector="{{CheckoutSuccessMainSection.successTitle}}" userInput="Thank you for your purchase!" stepKey="waitForLoadSuccessPage3"/> <!--Check "Print Receipt" button is presented (desktop only)--> <seeElement selector="{{CheckoutSuccessMainSection.printLink}}" stepKey="seeVisiblePrint"/> @@ -123,7 +120,6 @@ <!--See print page--> <click selector="{{CheckoutSuccessMainSection.printLink}}" stepKey="clickPrintLink"/> - <waitForPageLoad stepKey="waitPrintPage"/> <switchToWindow stepKey="switchToWindow"/> <switchToNextTab stepKey="switchToTab"/> <seeInCurrentUrl url="sales/order/print/order_id" stepKey="seePrintPage"/> @@ -169,7 +165,7 @@ <!--Click Place Order button--> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder"/> - <waitForElement selector="{{CheckoutSuccessMainSection.success}}" time="30" stepKey="waitForLoadSuccessPage"/> + <see selector="{{CheckoutSuccessMainSection.successTitle}}" userInput="Thank you for your purchase!" stepKey="waitForLoadSuccessPage"/> <!--See success messages--> <see selector="{{CheckoutSuccessMainSection.successTitle}}" userInput="Thank you for your purchase!" stepKey="seeSuccessTitle"/> @@ -181,7 +177,6 @@ <see selector="{{CheckoutSuccessRegisterSection.customerEmail}}" userInput="Email Address: {{CustomerEntityOne.email}}" stepKey="seeCustomerEmail"/> <seeElement selector="{{CheckoutSuccessRegisterSection.createAccountButton}}" stepKey="seeVisibleCreateAccountButton"/> <click selector="{{CheckoutSuccessRegisterSection.createAccountButton}}" stepKey="clickCreateAccountButton"/> - <waitForElement selector="{{StorefrontCMSPageSection.mainTitle}}" stepKey="waitAccountPage"/> <seeInCurrentUrl url="{{StorefrontCustomerCreatePage.url}}" stepKey="seeCreateAccountPage"/> <see userInput="Create New Customer Account" selector="{{StorefrontCMSPageSection.mainTitle}}" stepKey="seeCreateAccountPageTitle"/> @@ -203,11 +198,10 @@ <!--Click Place Order button--> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder2"/> - <waitForElement selector="{{CheckoutSuccessMainSection.success}}" time="30" stepKey="waitForLoadSuccessPage2"/> + <see selector="{{CheckoutSuccessMainSection.successTitle}}" userInput="Thank you for your purchase!" stepKey="waitForLoadSuccessPage2"/> <!--Continue shopping--> <click selector="{{CheckoutSuccessMainSection.continueShoppingButton}}" stepKey="clickContinueShoppingButton"/> - <waitForElement selector="{{StorefrontCMSPageSection.mainTitle}}" stepKey="waitHomePage"/> <seeCurrentUrlEquals url="{{_ENV.MAGENTO_BASE_URL}}" stepKey="seeHomePageUrl"/> <see userInput="Home Page" selector="{{StorefrontCMSPageSection.mainTitle}}" stepKey="seeHomePageTitle"/> </test> From 107aa22bf146ed70318f97ae4c987e11754de5ac Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 30 May 2018 10:48:27 +0300 Subject: [PATCH 0857/2023] MAGETWO-66217: Product Url key value comes from product name on storeview level (use default = yes) --- .../Product/Initialization/Helper.php | 57 ++++------- .../Initialization/Helper/AttributeFilter.php | 58 +++++++++-- .../Helper/AttributeFilterTest.php | 98 +++++++++++++------ 3 files changed, 141 insertions(+), 72 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php index beb6f2b13bcfe..95339870b4d61 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php @@ -3,14 +3,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Controller\Adminhtml\Product\Initialization; use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory as CustomOptionFactory; use Magento\Catalog\Api\Data\ProductLinkInterfaceFactory as ProductLinkFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Api\ProductRepositoryInterface\Proxy as ProductRepository; +use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper\AttributeDefaultValueFilter; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks; use Magento\Catalog\Model\Product\Link\Resolver as LinkResolver; +use Magento\Catalog\Model\Product\LinkTypeProvider; use Magento\Framework\App\ObjectManager; use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper\AttributeFilter; @@ -81,7 +85,7 @@ class Helper private $dateTimeFilter; /** - * @var \Magento\Catalog\Model\Product\LinkTypeProvider + * @var LinkTypeProvider */ private $linkTypeProvider; @@ -99,10 +103,10 @@ class Helper * @param ProductLinks $productLinks * @param \Magento\Backend\Helper\Js $jsHelper * @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter - * @param \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory|null $customOptionFactory - * @param \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory|null $productLinkFactory - * @param \Magento\Catalog\Api\ProductRepositoryInterface|null $productRepository - * @param \Magento\Catalog\Model\Product\LinkTypeProvider|null $linkTypeProvider + * @param CustomOptionFactory|null $customOptionFactory + * @param ProductLinkFactory |null $productLinkFactory + * @param ProductRepositoryInterface|null $productRepository + * @param LinkTypeProvider|null $linkTypeProvider * @param AttributeFilter|null $attributeFilter * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -113,10 +117,10 @@ public function __construct( \Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks $productLinks, \Magento\Backend\Helper\Js $jsHelper, \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter, - \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory = null, - \Magento\Catalog\Api\Data\ProductLinkInterfaceFactory $productLinkFactory = null, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository = null, - \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider = null, + CustomOptionFactory $customOptionFactory = null, + ProductLinkFactory $productLinkFactory = null, + ProductRepositoryInterface $productRepository = null, + LinkTypeProvider $linkTypeProvider = null, AttributeFilter $attributeFilter = null ) { $this->request = $request; @@ -125,16 +129,13 @@ public function __construct( $this->productLinks = $productLinks; $this->jsHelper = $jsHelper; $this->dateFilter = $dateFilter; - $this->customOptionFactory = $customOptionFactory ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); - $this->productLinkFactory = $productLinkFactory ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Catalog\Api\Data\ProductLinkInterfaceFactory::class); - $this->productRepository = $productRepository ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); - $this->linkTypeProvider = $linkTypeProvider ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Catalog\Model\Product\LinkTypeProvider::class); - $this->attributeFilter = $attributeFilter ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(AttributeFilter::class); + + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + $this->customOptionFactory = $customOptionFactory ?: $objectManager->get(CustomOptionFactory::class); + $this->productLinkFactory = $productLinkFactory ?: $objectManager->get(ProductLinkFactory::class); + $this->productRepository = $productRepository ?: $objectManager->get(ProductRepositoryInterface::class); + $this->linkTypeProvider = $linkTypeProvider ?: $objectManager->get(LinkTypeProvider::class); + $this->attributeFilter = $attributeFilter ?: $objectManager->get(AttributeFilter::class); } /** @@ -150,8 +151,7 @@ public function __construct( */ public function initializeFromData(\Magento\Catalog\Model\Product $product, array $productData) { - unset($productData['custom_attributes']); - unset($productData['extension_attributes']); + unset($productData['custom_attributes'], $productData['extension_attributes']); if ($productData) { $stockData = isset($productData['stock_data']) ? $productData['stock_data'] : []; @@ -199,28 +199,13 @@ public function initializeFromData(\Magento\Catalog\Model\Product $product, arra $productData['tier_price'] = isset($productData['tier_price']) ? $productData['tier_price'] : []; $useDefaults = (array)$this->request->getPost('use_default', []); - $productData = $this->attributeFilter->prepareProductAttributes($product, $productData, $useDefaults); - $product->addData($productData); if ($wasLockedMedia) { $product->lockAttribute('media'); } - /** - * Check "Use Default Value" checkboxes values - */ - foreach ($useDefaults as $attributeCode => $useDefaultState) { - if ($useDefaultState) { - $product->setData($attributeCode, null); - // UI component sends value even if field is disabled, so 'Use Config Settings' must be reset to false - if ($product->hasData('use_config_' . $attributeCode)) { - $product->setData('use_config_' . $attributeCode, false); - } - } - } - $product = $this->setProductLinks($product); $product = $this->fillProductOptions($product, $productOptions); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index ee3a6d491e92f..09af738a13201 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -28,11 +28,57 @@ class AttributeFilter * @param array $useDefaults * @return array */ - public function prepareProductAttributes(Product $product, array $productData, array $useDefaults) + public function prepareProductAttributes(Product $product, array $productData, array $useDefaults): array { - foreach ($productData as $attribute => $value) { - if ($this->isAttributeShouldNotBeUpdated($product, $useDefaults, $attribute, $value)) { - unset($productData[$attribute]); + $attributeList = $product->getAttributes(); + foreach ($productData as $attributeCode => $attributeValue) { + if ($this->isAttributeShouldNotBeUpdated($product, $useDefaults, $attributeCode, $attributeValue)) { + unset($productData[$attributeCode]); + } + + if (isset($useDefaults[$attributeCode]) && $useDefaults[$attributeCode] === '1') { + $productData = $this->prepareDefaultData($attributeList, $attributeCode, $productData); + $productData = $this->prepareConfigData($product, $attributeCode, $productData); + } + } + + return $productData; + } + + /** + * @param Product $product + * @param string $attributeCode + * @param array $productData + * @return array + */ + private function prepareConfigData(Product $product, $attributeCode, array $productData): array + { + // UI component sends value even if field is disabled, so 'Use Config Settings' must be reset to false + if ($product->hasData('use_config_' . $attributeCode)) { + $productData['use_config_' . $attributeCode] = false; + } + + return $productData; + } + + /** + * @param array $attributeList + * @param string $attributeCode + * @param array $productData + * @return array + */ + private function prepareDefaultData(array $attributeList, $attributeCode, array $productData): array + { + if (isset($attributeList[$attributeCode])) { + /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */ + $attribute = $attributeList[$attributeCode]; + $attributeType = $attribute->getBackendType(); + // For non-numberic types set the attributeValue to 'false' to trigger their removal from the db + if ($attributeType === 'varchar' || $attributeType === 'text' || $attributeType === 'datetime') { + $attribute->setIsRequired(false); + $productData[$attributeCode] = false; + } else { + $productData[$attributeCode] = null; } } @@ -46,9 +92,9 @@ public function prepareProductAttributes(Product $product, array $productData, a * @param $value * @return bool */ - private function isAttributeShouldNotBeUpdated(Product $product, $useDefaults, $attribute, $value) : bool + private function isAttributeShouldNotBeUpdated(Product $product, $useDefaults, $attribute, $value): bool { - $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === "1"; + $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === '1'; return ($value === '' && $considerUseDefaultsAttribute && !$product->getData($attribute)); } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilterTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilterTest.php index 28617addc6d27..6e25d02df53ee 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilterTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilterTest.php @@ -3,10 +3,13 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Initialization\Helper; use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper\AttributeFilter; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\ResourceModel\Eav\Attribute; +use PHPUnit_Framework_MockObject_MockObject; class AttributeFilterTest extends \PHPUnit\Framework\TestCase { @@ -16,12 +19,12 @@ class AttributeFilterTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var PHPUnit_Framework_MockObject_MockObject */ protected $objectManagerMock; /** - * @var Product|\PHPUnit_Framework_MockObject_MockObject + * @var Product|PHPUnit_Framework_MockObject_MockObject */ protected $productMock; @@ -44,15 +47,25 @@ public function testPrepareProductAttributes( $expectedProductData, $initialProductData ) { + /** @var PHPUnit_Framework_MockObject_MockObject | Product $productMockMap */ $productMockMap = $this->getMockBuilder(Product::class) ->disableOriginalConstructor() - ->setMethods(['getData']) + ->setMethods(['getData', 'getAttributes']) ->getMock(); if (!empty($initialProductData)) { $productMockMap->expects($this->any())->method('getData')->willReturnMap($initialProductData); } + if ($useDefaults) { + $productMockMap + ->expects($this->once()) + ->method('getAttributes') + ->willReturn( + $this->getProductAttributesMock($useDefaults) + ); + } + $actualProductData = $this->model->prepareProductAttributes($productMockMap, $requestProductData, $useDefaults); $this->assertEquals($expectedProductData, $actualProductData); } @@ -69,15 +82,15 @@ public function setupInputDataProvider() 'name' => 'testName', 'sku' => 'testSku', 'price' => '100', - 'description' => '' + 'description' => '', ], 'useDefaults' => [], 'expectedProductData' => [ 'name' => 'testName', 'sku' => 'testSku', - 'price' => '100' + 'price' => '100', ], - 'initialProductData' => [] + 'initialProductData' => [], ], 'update_product_without_use_defaults' => [ 'productData' => [ @@ -85,21 +98,21 @@ public function setupInputDataProvider() 'sku' => 'testSku2', 'price' => '101', 'description' => '', - 'special_price' => null + 'special_price' => null, ], 'useDefaults' => [], 'expectedProductData' => [ 'name' => 'testName2', 'sku' => 'testSku2', 'price' => '101', - 'special_price' => null + 'special_price' => null, ], 'initialProductData' => [ ['name', 'testName2'], ['sku', 'testSku2'], ['price', '101'], - ['special_price', null] - ] + ['special_price', null], + ], ], 'update_product_without_use_defaults_2' => [ 'productData' => [ @@ -107,7 +120,7 @@ public function setupInputDataProvider() 'sku' => 'testSku2', 'price' => '101', 'description' => 'updated description', - 'special_price' => null + 'special_price' => null, ], 'useDefaults' => [], 'expectedProductData' => [ @@ -115,14 +128,14 @@ public function setupInputDataProvider() 'sku' => 'testSku2', 'price' => '101', 'description' => 'updated description', - 'special_price' => null + 'special_price' => null, ], 'initialProductData' => [ ['name', 'testName2'], ['sku', 'testSku2'], ['price', '101'], - ['special_price', null] - ] + ['special_price', null], + ], ], 'update_product_with_use_defaults' => [ 'productData' => [ @@ -130,25 +143,25 @@ public function setupInputDataProvider() 'sku' => 'testSku2', 'price' => '101', 'description' => '', - 'special_price' => null + 'special_price' => null, ], 'useDefaults' => [ - 'description' => '0' + 'description' => '0', ], 'expectedProductData' => [ 'name' => 'testName2', 'sku' => 'testSku2', 'price' => '101', 'special_price' => null, - 'description' => '' + 'description' => '', ], 'initialProductData' => [ ['name', 'testName2'], ['sku', 'testSku2'], ['price', '101'], ['special_price', null], - ['description', 'descr text'] - ] + ['description', 'descr text'], + ], ], 'update_product_with_use_defaults_2' => [ 'requestProductData' => [ @@ -156,48 +169,73 @@ public function setupInputDataProvider() 'sku' => 'testSku3', 'price' => '103', 'description' => 'descr modified', - 'special_price' => '100' + 'special_price' => '100', ], 'useDefaults' => [ - 'description' => '0' + 'description' => '0', ], 'expectedProductData' => [ 'name' => 'testName3', 'sku' => 'testSku3', 'price' => '103', 'special_price' => '100', - 'description' => 'descr modified' + 'description' => 'descr modified', ], 'initialProductData' => [ - ['name', null,'testName2'], + ['name', null, 'testName2'], ['sku', null, 'testSku2'], ['price', null, '101'], - ['description', null, 'descr text'] - ] + ['description', null, 'descr text'], + ], ], 'update_product_with_use_defaults_3' => [ 'requestProductData' => [ 'name' => 'testName3', 'sku' => 'testSku3', 'price' => '103', - 'special_price' => '100' + 'special_price' => '100', + 'description' => 'descr modified', ], 'useDefaults' => [ - 'description' => '1' + 'description' => '1', ], 'expectedProductData' => [ 'name' => 'testName3', 'sku' => 'testSku3', 'price' => '103', 'special_price' => '100', + 'description' => false, ], 'initialProductData' => [ - ['name', null,'testName2'], + ['name', null, 'testName2'], ['sku', null, 'testSku2'], ['price', null, '101'], - ['description', null, 'descr text'] - ] + ['description', null, 'descr text'], + ], ], ]; } + + /** + * @param array $useDefaults + * @return array + */ + private function getProductAttributesMock(array $useDefaults): array + { + $returnArray = []; + foreach ($useDefaults as $attributecode => $isDefault) { + if ($isDefault === '1') { + /** @var Attribute | PHPUnit_Framework_MockObject_MockObject $attribute */ + $attribute = $this->getMockBuilder(Attribute::class) + ->disableOriginalConstructor() + ->getMock(); + $attribute->expects($this->any()) + ->method('getBackendType') + ->willReturn('varchar'); + + $returnArray[$attributecode] = $attribute; + } + } + return $returnArray; + } } From e71aa356ee43e9510706901065174444f42f1b8d Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Wed, 30 May 2018 10:58:49 +0300 Subject: [PATCH 0858/2023] MAGETWO-90349: Template file 'header.html' is not found. --- app/code/Magento/Email/Model/Template/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Email/Model/Template/Config.php b/app/code/Magento/Email/Model/Template/Config.php index d10c394dcb715..9b45f509d97e5 100644 --- a/app/code/Magento/Email/Model/Template/Config.php +++ b/app/code/Magento/Email/Model/Template/Config.php @@ -234,7 +234,7 @@ protected function _getInfo($templateId, $fieldName) /** * Retrieve template file path. - * + * * @param string $file * @param array $designParams * @param string $module From ea9c0f195600347f2e65031761260e8a7093fe31 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Wed, 30 May 2018 11:17:20 +0300 Subject: [PATCH 0859/2023] MAGETWO-90762: [2.3.0] Placing an order takes more time then usual --- .../Test/Unit/Model/GuestPaymentInformationManagementTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php index c4924ca211024..853ae0157e64a 100644 --- a/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Model/GuestPaymentInformationManagementTest.php @@ -168,7 +168,7 @@ public function testSavePaymentInformationAndPlaceOrderException() $adapterMockForCheckout->expects($this->once())->method('rollback'); $this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock); - $exception = new \Exception(__('DB exception')); + $exception = new \Magento\Framework\Exception\CouldNotSaveException(__('DB exception')); $this->cartManagementMock->expects($this->once())->method('placeOrder')->willThrowException($exception); $this->model->savePaymentInformationAndPlaceOrder($cartId, $email, $paymentMock, $billingAddressMock); From 6cc997ea2759c3039434395acef4960e665120bd Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Mon, 28 May 2018 20:34:17 +0200 Subject: [PATCH 0860/2023] [fix] PHPDoc and type hints --- app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php | 2 +- .../Catalog/Block/Adminhtml/Category/Widget/Chooser.php | 2 +- .../Catalog/Block/Adminhtml/Form/Renderer/Fieldset/Element.php | 2 +- .../Magento/Catalog/Block/Adminhtml/Product/Attribute/Grid.php | 3 +-- .../Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php | 2 +- app/code/Magento/Catalog/Block/Adminhtml/Rss/Grid/Link.php | 2 +- app/code/Magento/Catalog/Block/Category/Rss/Link.php | 2 +- app/code/Magento/Catalog/Block/Product/AbstractProduct.php | 2 +- .../Catalog/Block/Product/View/Options/AbstractOptions.php | 2 +- app/code/Magento/Catalog/Block/Rss/Product/Special.php | 2 +- 10 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php index 4b0d233d3e77b..34da5bb1d4ca1 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php @@ -325,7 +325,7 @@ public function getBreadcrumbsJavascript($path, $javascriptVarName) * * @param Node|array $node * @param int $level - * @return string + * @return array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Category/Widget/Chooser.php b/app/code/Magento/Catalog/Block/Adminhtml/Category/Widget/Chooser.php index 5e98313f95f0f..b5330ab66af71 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Category/Widget/Chooser.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Category/Widget/Chooser.php @@ -144,7 +144,7 @@ function (node, e) { * * @param \Magento\Framework\Data\Tree\Node|array $node * @param int $level - * @return string + * @return array */ protected function _getNodeJson($node, $level = 0) { diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Form/Renderer/Fieldset/Element.php b/app/code/Magento/Catalog/Block/Adminhtml/Form/Renderer/Fieldset/Element.php index 10214fc1d16fd..ad6df27b89334 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Form/Renderer/Fieldset/Element.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Form/Renderer/Fieldset/Element.php @@ -21,7 +21,7 @@ class Element extends \Magento\Backend\Block\Widget\Form\Renderer\Fieldset\Eleme /** * Retrieve data object related with form * - * @return \Magento\Catalog\Model\Product || \Magento\Catalog\Model\Category + * @return \Magento\Catalog\Model\Product|\Magento\Catalog\Model\Category */ public function getDataObject() { diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Grid.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Grid.php index ab5026b1e69b9..66e04ef03f771 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Grid.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Grid.php @@ -101,8 +101,7 @@ protected function _prepareColumns() 'type' => 'options', 'options' => ['1' => __('Yes'), '0' => __('No')], 'align' => 'center' - ], - 'is_user_defined' + ] ); $this->_eventManager->dispatch('product_attribute_grid_build', ['grid' => $this]); diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php index d5f66231f1d82..e1b97f996c769 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php @@ -81,7 +81,7 @@ public function getSelectorOptions() * * @param string $labelPart * @param int $templateId - * @return \Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection + * @return array */ public function getSuggestedAttributes($labelPart, $templateId = null) { diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Rss/Grid/Link.php b/app/code/Magento/Catalog/Block/Adminhtml/Rss/Grid/Link.php index dbeff93683bc0..9d13d89d54b80 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Rss/Grid/Link.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Rss/Grid/Link.php @@ -69,7 +69,7 @@ public function isRssAllowed() } /** - * @return string + * @return array */ protected function getLinkParams() { diff --git a/app/code/Magento/Catalog/Block/Category/Rss/Link.php b/app/code/Magento/Catalog/Block/Category/Rss/Link.php index 0599d5f4b989c..e40b81200574c 100644 --- a/app/code/Magento/Catalog/Block/Category/Rss/Link.php +++ b/app/code/Magento/Catalog/Block/Category/Rss/Link.php @@ -62,7 +62,7 @@ public function getLabel() } /** - * @return string + * @return array */ protected function getLinkParams() { diff --git a/app/code/Magento/Catalog/Block/Product/AbstractProduct.php b/app/code/Magento/Catalog/Block/Product/AbstractProduct.php index f22edd91e7914..4102c82a0a316 100644 --- a/app/code/Magento/Catalog/Block/Product/AbstractProduct.php +++ b/app/code/Magento/Catalog/Block/Product/AbstractProduct.php @@ -195,7 +195,7 @@ public function getAddToCompareUrl() * Gets minimal sales quantity * * @param \Magento\Catalog\Model\Product $product - * @return int|null + * @return float|null */ public function getMinimalQty($product) { diff --git a/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php b/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php index 66bf5eafb156e..d582005f653ef 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php +++ b/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php @@ -178,7 +178,7 @@ public function getPrice($price, $includingTax = null) * Returns price converted to current currency rate * * @param float $price - * @return float + * @return float|string */ public function getCurrencyPrice($price) { diff --git a/app/code/Magento/Catalog/Block/Rss/Product/Special.php b/app/code/Magento/Catalog/Block/Rss/Product/Special.php index c61bee4417cbc..a9107f14cc5e4 100644 --- a/app/code/Magento/Catalog/Block/Rss/Product/Special.php +++ b/app/code/Magento/Catalog/Block/Rss/Product/Special.php @@ -107,7 +107,7 @@ protected function _construct() } /** - * @return string + * @return array */ public function getRssData() { From 026da34ff1b8eaa069a316e9c84dcbf1811f34b1 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 30 May 2018 12:10:31 +0300 Subject: [PATCH 0861/2023] MAGETWO-89991: Change default AVS and CVV codes for Signifyd --- .../Magento/Braintree/Model/AvsEmsCodeMapper.php | 2 +- .../Test/Unit/Model/AvsEmsCodeMapperTest.php | 10 +++++----- .../Paypal/Model/Payflow/AvsEmsCodeMapper.php | 2 +- .../Unit/Model/Payflow/AvsEmsCodeMapperTest.php | 14 +++++++------- .../Signifyd/Model/PaymentVerificationFactory.php | 4 ++-- .../SignifydGateway/Debugger/DebuggerFactory.php | 2 +- .../SignifydGateway/Request/PurchaseBuilder.php | 6 +++++- app/code/Magento/Signifyd/etc/di.xml | 6 +----- .../Signifyd/Test/Repository/SignifydData.xml | 1 - .../Request/CreateCaseBuilderTest.php | 2 +- 10 files changed, 24 insertions(+), 25 deletions(-) diff --git a/app/code/Magento/Braintree/Model/AvsEmsCodeMapper.php b/app/code/Magento/Braintree/Model/AvsEmsCodeMapper.php index 1d5057d83d6cf..f9fae8a469b1d 100644 --- a/app/code/Magento/Braintree/Model/AvsEmsCodeMapper.php +++ b/app/code/Magento/Braintree/Model/AvsEmsCodeMapper.php @@ -24,7 +24,7 @@ class AvsEmsCodeMapper implements PaymentVerificationInterface * * @var string */ - private static $unavailableCode = 'U'; + private static $unavailableCode = ''; /** * List of mapping AVS codes diff --git a/app/code/Magento/Braintree/Test/Unit/Model/AvsEmsCodeMapperTest.php b/app/code/Magento/Braintree/Test/Unit/Model/AvsEmsCodeMapperTest.php index 9b80a2237a8fb..c82634d36db31 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/AvsEmsCodeMapperTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/AvsEmsCodeMapperTest.php @@ -84,11 +84,11 @@ public function testGetCodeWithException() public function getCodeDataProvider() { return [ - ['avsZip' => null, 'avsStreet' => null, 'expected' => 'U'], - ['avsZip' => null, 'avsStreet' => 'M', 'expected' => 'U'], - ['avsZip' => 'M', 'avsStreet' => null, 'expected' => 'U'], - ['avsZip' => 'M', 'avsStreet' => 'Unknown', 'expected' => 'U'], - ['avsZip' => 'I', 'avsStreet' => 'A', 'expected' => 'U'], + ['avsZip' => null, 'avsStreet' => null, 'expected' => ''], + ['avsZip' => null, 'avsStreet' => 'M', 'expected' => ''], + ['avsZip' => 'M', 'avsStreet' => null, 'expected' => ''], + ['avsZip' => 'M', 'avsStreet' => 'Unknown', 'expected' => ''], + ['avsZip' => 'I', 'avsStreet' => 'A', 'expected' => ''], ['avsZip' => 'M', 'avsStreet' => 'M', 'expected' => 'Y'], ['avsZip' => 'N', 'avsStreet' => 'M', 'expected' => 'A'], ['avsZip' => 'M', 'avsStreet' => 'N', 'expected' => 'Z'], diff --git a/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php b/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php index 661d1f3814a0b..1ec7f4832bcb2 100644 --- a/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php +++ b/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php @@ -24,7 +24,7 @@ class AvsEmsCodeMapper implements PaymentVerificationInterface * * @var string */ - private static $unavailableCode = 'U'; + private static $unavailableCode = ''; /** * List of mapping AVS codes diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/AvsEmsCodeMapperTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/AvsEmsCodeMapperTest.php index eb259043a2d4f..ea86a04206f7b 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/AvsEmsCodeMapperTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/AvsEmsCodeMapperTest.php @@ -85,17 +85,17 @@ public function testGetCodeWithException() public function getCodeDataProvider() { return [ - ['avsZip' => null, 'avsStreet' => null, 'expected' => 'U'], - ['avsZip' => null, 'avsStreet' => 'Y', 'expected' => 'U'], - ['avsZip' => 'Y', 'avsStreet' => null, 'expected' => 'U'], + ['avsZip' => null, 'avsStreet' => null, 'expected' => ''], + ['avsZip' => null, 'avsStreet' => 'Y', 'expected' => ''], + ['avsZip' => 'Y', 'avsStreet' => null, 'expected' => ''], ['avsZip' => 'Y', 'avsStreet' => 'Y', 'expected' => 'Y'], ['avsZip' => 'N', 'avsStreet' => 'Y', 'expected' => 'A'], ['avsZip' => 'Y', 'avsStreet' => 'N', 'expected' => 'Z'], ['avsZip' => 'N', 'avsStreet' => 'N', 'expected' => 'N'], - ['avsZip' => 'X', 'avsStreet' => 'Y', 'expected' => 'U'], - ['avsZip' => 'N', 'avsStreet' => 'X', 'expected' => 'U'], - ['avsZip' => '', 'avsStreet' => 'Y', 'expected' => 'U'], - ['avsZip' => 'N', 'avsStreet' => '', 'expected' => 'U'] + ['avsZip' => 'X', 'avsStreet' => 'Y', 'expected' => ''], + ['avsZip' => 'N', 'avsStreet' => 'X', 'expected' => ''], + ['avsZip' => '', 'avsStreet' => 'Y', 'expected' => ''], + ['avsZip' => 'N', 'avsStreet' => '', 'expected' => ''] ]; } } diff --git a/app/code/Magento/Signifyd/Model/PaymentVerificationFactory.php b/app/code/Magento/Signifyd/Model/PaymentVerificationFactory.php index a26beda520944..5be5ccbc5e55a 100644 --- a/app/code/Magento/Signifyd/Model/PaymentVerificationFactory.php +++ b/app/code/Magento/Signifyd/Model/PaymentVerificationFactory.php @@ -60,7 +60,7 @@ public function __construct( * * @param string $paymentCode * @return PaymentVerificationInterface - * @throws \Exception + * @throws ConfigurationMismatchException */ public function createPaymentCvv($paymentCode) { @@ -73,7 +73,7 @@ public function createPaymentCvv($paymentCode) * * @param string $paymentCode * @return PaymentVerificationInterface - * @throws \Exception + * @throws ConfigurationMismatchException */ public function createPaymentAvs($paymentCode) { diff --git a/app/code/Magento/Signifyd/Model/SignifydGateway/Debugger/DebuggerFactory.php b/app/code/Magento/Signifyd/Model/SignifydGateway/Debugger/DebuggerFactory.php index 02031e6f5b9b5..19408e99ae02e 100644 --- a/app/code/Magento/Signifyd/Model/SignifydGateway/Debugger/DebuggerFactory.php +++ b/app/code/Magento/Signifyd/Model/SignifydGateway/Debugger/DebuggerFactory.php @@ -30,7 +30,7 @@ class DebuggerFactory /** * DebuggerFactory constructor. * - * @param bjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager * @param Config $config */ public function __construct( diff --git a/app/code/Magento/Signifyd/Model/SignifydGateway/Request/PurchaseBuilder.php b/app/code/Magento/Signifyd/Model/SignifydGateway/Request/PurchaseBuilder.php index 858ce0f0f3287..5e544e4b4048e 100644 --- a/app/code/Magento/Signifyd/Model/SignifydGateway/Request/PurchaseBuilder.php +++ b/app/code/Magento/Signifyd/Model/SignifydGateway/Request/PurchaseBuilder.php @@ -7,12 +7,13 @@ use Magento\Framework\App\Area; use Magento\Framework\Config\ScopeInterface; +use Magento\Framework\Exception\ConfigurationMismatchException; use Magento\Framework\Intl\DateTimeFactory; use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Model\Order; +use Magento\Signifyd\Model\PaymentMethodMapper\PaymentMethodMapper; use Magento\Signifyd\Model\PaymentVerificationFactory; use Magento\Signifyd\Model\SignifydOrderSessionId; -use Magento\Signifyd\Model\PaymentMethodMapper\PaymentMethodMapper; /** * Prepare data related to purchase event represented in case creation request. @@ -72,6 +73,7 @@ public function __construct( * * @param Order $order * @return array + * @throws ConfigurationMismatchException */ public function build(Order $order) { @@ -202,6 +204,7 @@ private function getOrderChannel() * * @param OrderPaymentInterface $orderPayment * @return string + * @throws ConfigurationMismatchException */ private function getAvsCode(OrderPaymentInterface $orderPayment) { @@ -214,6 +217,7 @@ private function getAvsCode(OrderPaymentInterface $orderPayment) * * @param OrderPaymentInterface $orderPayment * @return string + * @throws ConfigurationMismatchException */ private function getCvvCode(OrderPaymentInterface $orderPayment) { diff --git a/app/code/Magento/Signifyd/etc/di.xml b/app/code/Magento/Signifyd/etc/di.xml index 92ad8a0bfd87a..fd78fff27f619 100644 --- a/app/code/Magento/Signifyd/etc/di.xml +++ b/app/code/Magento/Signifyd/etc/di.xml @@ -15,11 +15,7 @@ <preference for="Magento\Signifyd\Api\GuaranteeCancelingServiceInterface" type="Magento\Signifyd\Model\Guarantee\CancelingService" /> <preference for="Magento\Signifyd\Model\SignifydGateway\Request\CreateCaseBuilderInterface" type="Magento\Signifyd\Model\SignifydGateway\Request\CreateCaseBuilder" /> - <virtualType name="SignifydAvsDefaultMapper" type="Magento\Signifyd\Model\PredefinedVerificationCode"> - <arguments> - <argument name="code" xsi:type="string">U</argument> - </arguments> - </virtualType> + <virtualType name="SignifydAvsDefaultMapper" type="Magento\Signifyd\Model\PredefinedVerificationCode" /> <virtualType name="SignifydCvvDefaultMapper" type="Magento\Signifyd\Model\PredefinedVerificationCode" /> <type name="Magento\Signifyd\Model\PaymentVerificationFactory"> diff --git a/dev/tests/functional/tests/app/Magento/Signifyd/Test/Repository/SignifydData.xml b/dev/tests/functional/tests/app/Magento/Signifyd/Test/Repository/SignifydData.xml index 5b3be4b9d570a..02037534b0149 100644 --- a/dev/tests/functional/tests/app/Magento/Signifyd/Test/Repository/SignifydData.xml +++ b/dev/tests/functional/tests/app/Magento/Signifyd/Test/Repository/SignifydData.xml @@ -27,7 +27,6 @@ <field name="team" xsi:type="string">autotest</field> <field name="caseFlag" xsi:type="string">Bad</field> <field name="guaranteeDisposition" xsi:type="string">Declined</field> - <field name="avsResponse" xsi:type="string">Unavailable (U)</field> <field name="shippingPrice" xsi:type="string">GBP 10.00</field> </dataset> </repository> diff --git a/dev/tests/integration/testsuite/Magento/Signifyd/Model/SignifydGateway/Request/CreateCaseBuilderTest.php b/dev/tests/integration/testsuite/Magento/Signifyd/Model/SignifydGateway/Request/CreateCaseBuilderTest.php index e53e0c26e286a..594c065185ac7 100644 --- a/dev/tests/integration/testsuite/Magento/Signifyd/Model/SignifydGateway/Request/CreateCaseBuilderTest.php +++ b/dev/tests/integration/testsuite/Magento/Signifyd/Model/SignifydGateway/Request/CreateCaseBuilderTest.php @@ -86,7 +86,7 @@ public function testCreateCaseBuilderWithFullSetOfData() 'paymentGateway' => 'paypal_account', 'transactionId' => $payment->getLastTransId(), 'currency' => $order->getOrderCurrencyCode(), - 'avsResponseCode' => 'U', + 'avsResponseCode' => '', 'cvvResponseCode' => '', 'orderChannel' => 'WEB', 'totalPrice' => $order->getGrandTotal(), From d6aabc3f7a115627d7c1c766e76045d5390b8588 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Wed, 30 May 2018 12:27:20 +0300 Subject: [PATCH 0862/2023] Update MagentoStyle.php --- setup/src/Magento/Setup/Console/Style/MagentoStyle.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Console/Style/MagentoStyle.php b/setup/src/Magento/Setup/Console/Style/MagentoStyle.php index e709d9158a049..cd2d4a77db65a 100755 --- a/setup/src/Magento/Setup/Console/Style/MagentoStyle.php +++ b/setup/src/Magento/Setup/Console/Style/MagentoStyle.php @@ -519,7 +519,7 @@ private function autoPrependText() } /** - * @param $messages + * @param array $messages * @return array */ private function reduceBuffer($messages) From aa41f77d390917562f227ae80dc9038630e82594 Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Wed, 30 May 2018 13:01:14 +0300 Subject: [PATCH 0863/2023] MAGETWO-92134: [2.2.x] Payment Failed Email is not generated --- .../Magento/Authorizenet/Model/Directpost.php | 6 +- .../Checkout/Test/Unit/Helper/DataTest.php | 60 +++++++++---------- app/code/Magento/Paypal/Model/Payflowpro.php | 1 - .../Model/Service/PaymentFailuresService.php | 13 ++-- .../Magento/Paypal/Controller/PayflowTest.php | 4 +- .../Paypal/Controller/PayflowadvancedTest.php | 8 +-- .../Service/PaymentFailuresServiceTest.php | 2 +- 7 files changed, 46 insertions(+), 48 deletions(-) diff --git a/app/code/Magento/Authorizenet/Model/Directpost.php b/app/code/Magento/Authorizenet/Model/Directpost.php index de567a8895f7e..5476fd05a0fed 100644 --- a/app/code/Magento/Authorizenet/Model/Directpost.php +++ b/app/code/Magento/Authorizenet/Model/Directpost.php @@ -143,8 +143,8 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra * @param \Magento\Framework\Module\ModuleListInterface $moduleList * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Authorizenet\Helper\Data $dataHelper - * @param Directpost\Request\Factory $requestFactory - * @param Directpost\Response\Factory $responseFactory + * @param \Magento\Authorizenet\Model\Directpost\Request\Factory $requestFactory + * @param \Magento\Authorizenet\Model\Directpost\Response\Factory $responseFactory * @param \Magento\Authorizenet\Model\TransactionService $transactionService * @param \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory * @param \Magento\Sales\Model\OrderFactory $orderFactory @@ -171,7 +171,7 @@ public function __construct( \Magento\Authorizenet\Helper\Data $dataHelper, \Magento\Authorizenet\Model\Directpost\Request\Factory $requestFactory, \Magento\Authorizenet\Model\Directpost\Response\Factory $responseFactory, - TransactionService $transactionService, + \Magento\Authorizenet\Model\TransactionService $transactionService, \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory, \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, diff --git a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php index f6f9ff78c1cb2..53132ffaa748b 100644 --- a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php @@ -23,32 +23,32 @@ class DataTest extends \PHPUnit\Framework\TestCase /** * @var Data */ - private $_helper; + private $helper; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - private $_transportBuilder; + private $transportBuilder; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - private $_translator; + private $translator; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - private $_checkoutSession; + private $checkoutSession; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - private $_scopeConfig; + private $scopeConfig; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - private $_eventManager; + private $eventManager; /** * @inheritdoc @@ -60,10 +60,10 @@ protected function setUp() $arguments = $objectManagerHelper->getConstructArguments($className); /** @var \Magento\Framework\App\Helper\Context $context */ $context = $arguments['context']; - $this->_translator = $arguments['inlineTranslation']; - $this->_eventManager = $context->getEventManager(); - $this->_scopeConfig = $context->getScopeConfig(); - $this->_scopeConfig->expects($this->any()) + $this->translator = $arguments['inlineTranslation']; + $this->eventManager = $context->getEventManager(); + $this->scopeConfig = $context->getScopeConfig(); + $this->scopeConfig->expects($this->any()) ->method('getValue') ->willReturnMap( [ @@ -118,16 +118,16 @@ protected function setUp() ] ); - $this->_checkoutSession = $arguments['checkoutSession']; + $this->checkoutSession = $arguments['checkoutSession']; $arguments['localeDate']->expects($this->any()) ->method('formatDateTime') ->willReturn('Oct 02, 2013'); - $this->_transportBuilder = $arguments['transportBuilder']; + $this->transportBuilder = $arguments['transportBuilder']; $this->priceCurrency = $arguments['priceCurrency']; - $this->_helper = $objectManagerHelper->getObject($className, $arguments); + $this->helper = $objectManagerHelper->getObject($className, $arguments); } /** @@ -141,7 +141,7 @@ public function testSendPaymentFailedEmail() ->getMock(); $quoteMock->expects($this->any())->method('getId')->willReturn(1); - $this->assertSame($this->_helper, $this->_helper->sendPaymentFailedEmail($quoteMock, 'test message')); + $this->assertSame($this->helper, $this->helper->sendPaymentFailedEmail($quoteMock, 'test message')); } /** @@ -149,14 +149,14 @@ public function testSendPaymentFailedEmail() */ public function testGetCheckout() { - $this->assertEquals($this->_checkoutSession, $this->_helper->getCheckout()); + $this->assertEquals($this->checkoutSession, $this->helper->getCheckout()); } public function testGetQuote() { $quoteMock = $this->createMock(\Magento\Quote\Model\Quote::class); - $this->_checkoutSession->expects($this->once())->method('getQuote')->will($this->returnValue($quoteMock)); - $this->assertEquals($quoteMock, $this->_helper->getQuote()); + $this->checkoutSession->expects($this->once())->method('getQuote')->will($this->returnValue($quoteMock)); + $this->assertEquals($quoteMock, $this->helper->getQuote()); } public function testFormatPrice() @@ -164,26 +164,26 @@ public function testFormatPrice() $price = 5.5; $quoteMock = $this->createMock(\Magento\Quote\Model\Quote::class); $storeMock = $this->createPartialMock(\Magento\Store\Model\Store::class, ['formatPrice', '__wakeup']); - $this->_checkoutSession->expects($this->once())->method('getQuote')->will($this->returnValue($quoteMock)); + $this->checkoutSession->expects($this->once())->method('getQuote')->will($this->returnValue($quoteMock)); $quoteMock->expects($this->once())->method('getStore')->will($this->returnValue($storeMock)); $this->priceCurrency->expects($this->once())->method('format')->will($this->returnValue('5.5')); - $this->assertEquals('5.5', $this->_helper->formatPrice($price)); + $this->assertEquals('5.5', $this->helper->formatPrice($price)); } public function testConvertPrice() { $price = 5.5; $this->priceCurrency->expects($this->once())->method('convertAndFormat')->willReturn($price); - $this->assertEquals(5.5, $this->_helper->convertPrice($price)); + $this->assertEquals(5.5, $this->helper->convertPrice($price)); } public function testCanOnepageCheckout() { - $this->_scopeConfig->expects($this->once())->method('getValue')->with( + $this->scopeConfig->expects($this->once())->method('getValue')->with( 'checkout/options/onepage_checkout_enabled', 'store' )->will($this->returnValue(true)); - $this->assertTrue($this->_helper->canOnepageCheckout()); + $this->assertTrue($this->helper->canOnepageCheckout()); } public function testIsContextCheckout() @@ -204,18 +204,18 @@ public function testIsContextCheckout() public function testIsCustomerMustBeLogged() { - $this->_scopeConfig->expects($this->once())->method('isSetFlag')->with( + $this->scopeConfig->expects($this->once())->method('isSetFlag')->with( 'checkout/options/customer_must_be_logged', \Magento\Store\Model\ScopeInterface::SCOPE_STORE )->will($this->returnValue(true)); - $this->assertTrue($this->_helper->isCustomerMustBeLogged()); + $this->assertTrue($this->helper->isCustomerMustBeLogged()); } public function testGetPriceInclTax() { $itemMock = $this->createPartialMock(\Magento\Framework\DataObject::class, ['getPriceInclTax']); $itemMock->expects($this->exactly(2))->method('getPriceInclTax')->will($this->returnValue(5.5)); - $this->assertEquals(5.5, $this->_helper->getPriceInclTax($itemMock)); + $this->assertEquals(5.5, $this->helper->getPriceInclTax($itemMock)); } public function testGetPriceInclTaxWithoutTax() @@ -256,7 +256,7 @@ public function testGetSubtotalInclTax() $expected = 5.5; $itemMock = $this->createPartialMock(\Magento\Framework\DataObject::class, ['getRowTotalInclTax']); $itemMock->expects($this->exactly(2))->method('getRowTotalInclTax')->will($this->returnValue($rowTotalInclTax)); - $this->assertEquals($expected, $this->_helper->getSubtotalInclTax($itemMock)); + $this->assertEquals($expected, $this->helper->getSubtotalInclTax($itemMock)); } public function testGetSubtotalInclTaxNegative() @@ -274,7 +274,7 @@ public function testGetSubtotalInclTaxNegative() $itemMock->expects($this->once()) ->method('getDiscountTaxCompensation')->will($this->returnValue($discountTaxCompensation)); $itemMock->expects($this->once())->method('getRowTotal')->will($this->returnValue($rowTotal)); - $this->assertEquals($expected, $this->_helper->getSubtotalInclTax($itemMock)); + $this->assertEquals($expected, $this->helper->getSubtotalInclTax($itemMock)); } public function testGetBasePriceInclTaxWithoutQty() @@ -321,7 +321,7 @@ public function testGetBaseSubtotalInclTax() $itemMock->expects($this->once())->method('getBaseTaxAmount'); $itemMock->expects($this->once())->method('getBaseDiscountTaxCompensation'); $itemMock->expects($this->once())->method('getBaseRowTotal'); - $this->_helper->getBaseSubtotalInclTax($itemMock); + $this->helper->getBaseSubtotalInclTax($itemMock); } public function testIsAllowedGuestCheckoutWithoutStore() @@ -329,9 +329,9 @@ public function testIsAllowedGuestCheckoutWithoutStore() $quoteMock = $this->createMock(\Magento\Quote\Model\Quote::class); $store = null; $quoteMock->expects($this->once())->method('getStoreId')->will($this->returnValue(1)); - $this->_scopeConfig->expects($this->once()) + $this->scopeConfig->expects($this->once()) ->method('isSetFlag') ->will($this->returnValue(true)); - $this->assertTrue($this->_helper->isAllowedGuestCheckout($quoteMock, $store)); + $this->assertTrue($this->helper->isAllowedGuestCheckout($quoteMock, $store)); } } diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php index 16ba4efc90d6a..b5fdaf4ae9fd4 100644 --- a/app/code/Magento/Paypal/Model/Payflowpro.php +++ b/app/code/Magento/Paypal/Model/Payflowpro.php @@ -647,7 +647,6 @@ public function buildBasicRequest() * * @param DataObject $response * @return void - * @throws \Magento\Framework\Exception\LocalizedException * @throws \Magento\Payment\Gateway\Command\CommandException * @throws \Magento\Framework\Exception\State\InvalidTransitionException */ diff --git a/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php b/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php index 2e8da0dadd5b1..6da1dc1b7e7cc 100644 --- a/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php +++ b/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php @@ -189,10 +189,12 @@ private function getConfigValue(string $configPath, Quote $quote) * @param Quote $quote * @return string */ - private function getShippingMethod(Quote $quote) + private function getShippingMethod(Quote $quote): string { $shippingMethod = ''; - if ($shippingInfo = $quote->getShippingAddress()->getShippingMethod()) { + $shippingInfo = $quote->getShippingAddress()->getShippingMethod(); + + if ($shippingInfo) { $data = explode('_', $shippingInfo); $shippingMethod = $data[0]; } @@ -206,12 +208,9 @@ private function getShippingMethod(Quote $quote) * @param Quote $quote * @return string */ - private function getPaymentMethod(Quote $quote) + private function getPaymentMethod(Quote $quote): string { - $paymentMethod = ''; - if ($paymentInfo = $quote->getPayment()) { - $paymentMethod = $paymentInfo->getMethod(); - } + $paymentMethod = $quote->getPayment()->getMethod() ?? ''; return $paymentMethod; } diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowTest.php index 367f68ce25872..670cc6850b233 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowTest.php @@ -63,7 +63,7 @@ protected function setUp() $this->order->getPayment()->setMethod(Config::METHOD_PAYFLOWLINK); /** @var $quote \Magento\Quote\Model\Quote */ - $quote = $this->_objectManager->create(Quote::class)->setStoreid($this->order->getStoreid()); + $quote = $this->_objectManager->create(Quote::class)->setStoreid($this->order->getStoreId()); $this->quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class); $this->quoteRepository->save($quote); @@ -111,7 +111,7 @@ public function testFormActionIsContentGenerated() * @magentoConfigFixture current_store paypal/general/business_account merchant_2012050718_biz@example.com * @return void */ - public function testCancelAction() + public function testCancelAction(): void { $orderId = $this->order->getEntityId(); /** @var \Magento\Sales\Model\Order $order */ diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowadvancedTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowadvancedTest.php index 7996acc7ed3b0..bf404f74b769e 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowadvancedTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/PayflowadvancedTest.php @@ -60,11 +60,11 @@ protected function setUp() /** @var OrderInterface $order */ $this->order = array_pop($orders); - $this->order->getPayment()->setMethod(Config::METHOD_PAYFLOWLINK); + $this->order->getPayment()->setMethod(Config::METHOD_PAYFLOWADVANCED); /** @var $quote \Magento\Quote\Model\Quote */ $quote = $this->_objectManager->create(Quote::class) - ->setStoreid($this->order->getStoreid()); + ->setStoreid($this->order->getStoreId()); $this->quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class); $this->quoteRepository->save($quote); @@ -104,7 +104,7 @@ public function testFormActionIsContentGenerated() * @magentoConfigFixture current_store paypal/general/business_account merchant_2012050718_biz@example.com * @return void */ - public function testCancelAction() + public function testCancelAction(): void { $orderId = $this->order->getEntityId(); /** @var \Magento\Sales\Model\Order $order */ @@ -115,7 +115,7 @@ public function testCancelAction() $session = $this->_objectManager->get(Session::class); $session->setQuoteId($quote->getId()); $session->setPaypalStandardQuoteId($quote->getId())->setLastRealOrderId('100000001'); - $this->dispatch('paypal/payflow/cancelpayment'); + $this->dispatch('paypal/payflowadvanced/cancelpayment'); $order = $this->_objectManager->create(OrderRepositoryInterface::class)->get($orderId); $this->assertEquals('canceled', $order->getState()); diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php index 1e334c9660d19..6367ff6d1a6d3 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php @@ -59,7 +59,7 @@ protected function setUp() * @magentoAppIsolation enabled * @return void */ - public function testHandlerWithCustomer() + public function testHandlerWithCustomer(): void { $errorMessage = __('Transaction declined.'); $checkoutType = 'custom_checkout'; From 556bad21bfa142260f3dd9f7d0a2636c77067d06 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Wed, 30 May 2018 14:17:32 +0300 Subject: [PATCH 0864/2023] MAGETWO-89407: [2.3] PayPal Payments Pro settings gets from wrong store --- .../Service/Request/SecureTokenTest.php | 24 +++++++++++++------ .../_files/quote_payflowpro_rollback.php | 3 +++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Payflow/Service/Request/SecureTokenTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/Payflow/Service/Request/SecureTokenTest.php index df6a1aae3fdb8..2318edbb80b25 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Payflow/Service/Request/SecureTokenTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Payflow/Service/Request/SecureTokenTest.php @@ -70,7 +70,7 @@ protected function setUp() $this->service = $this->objectManager->create( SecureToken::class, [ - 'mathRandom' => $this->mathRandom + 'mathRandom' => $this->mathRandom, ] ); } @@ -89,8 +89,9 @@ protected function tearDown() * @magentoDataFixture Magento/Paypal/_files/quote_payflowpro.php * @magentoDataFixture Magento/Paypal/Fixtures/default_payment_configuration.php * @magentoAppArea adminhtml + * @return void */ - public function testRequestToken() + public function testRequestToken(): void { $quote = $this->getQuote('100000015'); $quote->setStoreId(null); @@ -103,8 +104,9 @@ public function testRequestToken() * @magentoDataFixture Magento/Paypal/_files/quote_payflowpro.php * @magentoDataFixture Magento/Paypal/Fixtures/store_payment_configuration.php * @magentoAppArea adminhtml + * @return void */ - public function testRequestTokenWithStoreConfiguration() + public function testRequestTokenWithStoreConfiguration(): void { $quote = $this->getQuote('100000015'); $store = $this->getStore('test'); @@ -118,8 +120,9 @@ public function testRequestTokenWithStoreConfiguration() * @magentoDataFixture Magento/Paypal/_files/quote_payflowpro.php * @magentoDataFixture Magento/Paypal/Fixtures/website_payment_configuration.php * @magentoAppArea adminhtml + * @return void */ - public function testRequestTokenWithWebsiteConfiguration() + public function testRequestTokenWithWebsiteConfiguration(): void { $quote = $this->getQuote('100000015'); $store = $this->getStore('fixture_second_store'); @@ -135,9 +138,15 @@ public function testRequestTokenWithWebsiteConfiguration() * @param string $expVendor * @param string $expUser * @param string $expPwd + * @return void */ - private function execute(Quote $quote, string $expPartner, string $expVendor, string $expUser, string $expPwd) - { + private function execute( + Quote $quote, + string $expPartner, + string $expVendor, + string $expUser, + string $expPwd + ): void { $secureTokenId = '31f2a7c8d257c70b1c9eb9051b90e0'; $token = '80IgSbabyj0CtBDWHZZeQN3'; @@ -174,8 +183,9 @@ private function execute(Quote $quote, string $expPartner, string $expVendor, st * @param string $expected * @param string $actual * @param string $property + * @return void */ - private function performAssertion(string $expected, string $actual, string $property) + private function performAssertion(string $expected, string $actual, string $property): void { self::assertEquals($expected, $actual, "$property should match."); } diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php index 6eded10e5c555..32a76834dbf27 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payflowpro_rollback.php @@ -45,3 +45,6 @@ $quote = array_pop($items); $quoteRepository->delete($quote); } + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); From 87a2f1bd57a089a89d45f0de1fcbbf7d1530c1ff Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Wed, 30 May 2018 09:50:07 -0500 Subject: [PATCH 0865/2023] MAGETWO-91848: Hint on product option with Maximum Characters should count down as more characters are entered --- .../frontend/js/product/remaining-characters.test.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Catalog/frontend/js/product/remaining-characters.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Catalog/frontend/js/product/remaining-characters.test.js index cab3acdd63480..468d3e118fbe0 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Catalog/frontend/js/product/remaining-characters.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Catalog/frontend/js/product/remaining-characters.test.js @@ -26,8 +26,12 @@ define([ }); }); - describe('Note text is updated on input change', function () { + afterEach(function () { + widget.remove(); + note.remove(); + }); + describe('Note text is updated on input change', function () { it('check empty input', function () { var testData = { input: '', @@ -75,7 +79,6 @@ define([ widget.trigger(testData.action); expect(note.find('.character-counter').text()).toBe(testData.expectedText); }); - }); }); }); From fdacd0d73579dccc8f945ba844a91cbf686b1f40 Mon Sep 17 00:00:00 2001 From: Alex Paliarush <apaliarush@magento.com> Date: Wed, 30 May 2018 10:42:40 -0500 Subject: [PATCH 0866/2023] MAGETWO-92260: GraphQL - Fix urlResolver query to support relative path #13 --- .../CmsUrlRewriteGraphQl/composer.json | 9 ++-- .../Magento/UrlRewriteGraphQl/composer.json | 46 +++++++++---------- .../Magento/Test/Integrity/ComposerTest.php | 2 +- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/app/code/Magento/CmsUrlRewriteGraphQl/composer.json b/app/code/Magento/CmsUrlRewriteGraphQl/composer.json index 1e0c836389340..c57e4cdc92a83 100644 --- a/app/code/Magento/CmsUrlRewriteGraphQl/composer.json +++ b/app/code/Magento/CmsUrlRewriteGraphQl/composer.json @@ -4,13 +4,14 @@ "type": "magento2-module", "require": { "php": "~7.1.3||~7.2.0", - "magento/framework": "*" - + "magento/framework": "*", + "magento/module-url-rewrite-graph-ql": "*", + "magento/module-store": "*", + "magento/module-cms": "*" }, "suggest": { "magento/module-cms-url-rewrite": "*", - "magento/module-catalog-graph-ql": "*", - "magento/module-url-rewrite-graph-ql": "*" + "magento/module-catalog-graph-ql": "*" }, "license": [ "OSL-3.0", diff --git a/app/code/Magento/UrlRewriteGraphQl/composer.json b/app/code/Magento/UrlRewriteGraphQl/composer.json index 8d5295a2389fa..1c99276269aa7 100644 --- a/app/code/Magento/UrlRewriteGraphQl/composer.json +++ b/app/code/Magento/UrlRewriteGraphQl/composer.json @@ -1,26 +1,26 @@ { - "name" : "magento/module-url-rewrite-graph-ql", - "description" : "N/A", - "type" : "magento2-module", - "require" : { - "php" : "~7.1.3||~7.2.0", - "magento/framework" : "*", - "magento/module-url-rewrite" : "*", + "name": "magento/module-url-rewrite-graph-ql", + "description": "N/A", + "type": "magento2-module", + "require": { + "php": "~7.1.3||~7.2.0", + "magento/framework": "*", + "magento/module-url-rewrite": "*", "magento/module-store": "*" - }, - "suggest" : { - "magento/module-graph-ql" : "*" - }, - "license" : [ - "OSL-3.0", - "AFL-3.0" - ], - "autoload" : { - "files" : [ - "registration.php" - ], - "psr-4" : { - "Magento\\UrlRewriteGraphQl\\" : "" - } - } + }, + "suggest": { + "magento/module-graph-ql": "*" + }, + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Magento\\UrlRewriteGraphQl\\": "" + } + } } diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php index d671efe10fb6e..a42fe147303bb 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php @@ -144,7 +144,7 @@ private function validateComposerJsonFile($path) */ private function assertCodingStyle($contents) { - $this->assertNotRegExp('/" :\s*["{]/', $contents, 'Coding style: no space before colon.'); + $this->assertNotRegExp('/" :\s*["{]/', $contents, 'Coding style: there should be no space before colon.'); $this->assertNotRegExp('/":["{]/', $contents, 'Coding style: a space is necessary after colon.'); } From 1e2019ccb7f39c4158f77258cec6d52f32011d70 Mon Sep 17 00:00:00 2001 From: Brian LaBelle <labelle.brian.c@gmail.com> Date: Thu, 24 May 2018 10:40:38 -0500 Subject: [PATCH 0867/2023] Issue 15469: Javascript error dropdowns.js Fixes Javascript error in dropdowns.js by properly initializing the el variable. options.autoclose can now be set to false --- lib/web/mage/dropdowns.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/web/mage/dropdowns.js b/lib/web/mage/dropdowns.js index 6c1389924a24b..1496a1c65d957 100644 --- a/lib/web/mage/dropdowns.js +++ b/lib/web/mage/dropdowns.js @@ -127,11 +127,9 @@ define([ } elem.on('click.toggleDropdown', function () { - var el; + var el = actionElem; if (options.autoclose === true) { - el = actionElem; - actionElem = $(); $(document).trigger('click.hideDropdown'); actionElem = el; From 3b3dcd44914887e1b3f8f1e637647365f23c5562 Mon Sep 17 00:00:00 2001 From: Alex Paliarush <apaliarush@magento.com> Date: Wed, 30 May 2018 13:15:14 -0500 Subject: [PATCH 0868/2023] MAGETWO-92260: GraphQL - Fix urlResolver query to support relative path #13 --- ...UrlResolver.php => HomePageUrlLocator.php} | 8 ++-- .../Magento/CmsUrlRewriteGraphQl/etc/di.xml | 6 +-- .../Model/Resolver/UrlRewrite.php | 14 +++---- .../Resolver/UrlRewrite/CustomUrlLocator.php | 41 +++++++++++++++++++ ...face.php => CustomUrlLocatorInterface.php} | 4 +- .../Resolver/UrlRewrite/CustomUrlResolver.php | 41 ------------------- app/code/Magento/UrlRewriteGraphQl/etc/di.xml | 2 +- 7 files changed, 58 insertions(+), 58 deletions(-) rename app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/{HomePageUrlResolver.php => HomePageUrlLocator.php} (86%) create mode 100644 app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlLocator.php rename app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/{CustomUrlResolverInterface.php => CustomUrlLocatorInterface.php} (84%) delete mode 100644 app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolver.php diff --git a/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlResolver.php b/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlLocator.php similarity index 86% rename from app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlResolver.php rename to app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlLocator.php index d20323a485d71..6cc669e46d080 100644 --- a/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlResolver.php +++ b/app/code/Magento/CmsUrlRewriteGraphQl/Model/Resolver/UrlRewrite/HomePageUrlLocator.php @@ -7,14 +7,14 @@ namespace Magento\CmsUrlRewriteGraphQl\Model\Resolver\UrlRewrite; -use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolverInterface; +use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface; use Magento\Store\Model\ScopeInterface; use Magento\Cms\Helper\Page; /** - * Home page URL resolver. + * Home page URL locator. */ -class HomePageUrlResolver implements CustomUrlResolverInterface +class HomePageUrlLocator implements CustomUrlLocatorInterface { /** * @var \Magento\Framework\App\Config\ScopeConfigInterface @@ -33,7 +33,7 @@ public function __construct( /** * @inheritdoc */ - public function resolveUrl($urlKey): ?string + public function locateUrl($urlKey): ?string { if ($urlKey === '/') { $homePageUrl = $this->scopeConfig->getValue( diff --git a/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml b/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml index 8cd226b3fd258..d384c898acb62 100644 --- a/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml +++ b/app/code/Magento/CmsUrlRewriteGraphQl/etc/di.xml @@ -6,10 +6,10 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> - <type name="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolver"> + <type name="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocator"> <arguments> - <argument name="urlResolvers" xsi:type="array"> - <item name="homePageResolver" xsi:type="object">Magento\CmsUrlRewriteGraphQl\Model\Resolver\UrlRewrite\HomePageUrlResolver</item> + <argument name="urlLocators" xsi:type="array"> + <item name="homePageUrlLocator" xsi:type="object">Magento\CmsUrlRewriteGraphQl\Model\Resolver\UrlRewrite\HomePageUrlLocator</item> </argument> </arguments> </type> diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php index 0de21c81f7a8c..3f07edc601909 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php @@ -14,7 +14,7 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\UrlRewrite\Model\UrlFinderInterface; -use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolverInterface; +use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface; /** * UrlRewrite field resolver, used for GraphQL request processing. @@ -37,26 +37,26 @@ class UrlRewrite implements ResolverInterface private $valueFactory; /** - * @var UrlRewrite\CustomUrlResolverInterface + * @var CustomUrlLocatorInterface */ - private $customUrlResolver; + private $customUrlLocator; /** * @param UrlFinderInterface $urlFinder * @param StoreManagerInterface $storeManager * @param ValueFactory $valueFactory - * @param CustomUrlResolverInterface $customUrlResolver + * @param CustomUrlLocatorInterface $customUrlLocator */ public function __construct( UrlFinderInterface $urlFinder, StoreManagerInterface $storeManager, ValueFactory $valueFactory, - CustomUrlResolverInterface $customUrlResolver + CustomUrlLocatorInterface $customUrlLocator ) { $this->urlFinder = $urlFinder; $this->storeManager = $storeManager; $this->valueFactory = $valueFactory; - $this->customUrlResolver = $customUrlResolver; + $this->customUrlLocator = $customUrlLocator; } /** @@ -78,7 +78,7 @@ public function resolve( if (substr($url, 0, 1) === '/' && $url !== '/') { $url = ltrim($url, '/'); } - $customUrl = $this->customUrlResolver->resolveUrl($url); + $customUrl = $this->customUrlLocator->locateUrl($url); $url = $customUrl ?: $url; $urlRewrite = $this->findCanonicalUrl($url); if ($urlRewrite) { diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlLocator.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlLocator.php new file mode 100644 index 0000000000000..553c08e29137a --- /dev/null +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlLocator.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite; + +/** + * Pool of custom URL locators. + */ +class CustomUrlLocator implements CustomUrlLocatorInterface +{ + /** + * @var CustomUrlLocatorInterface[] + */ + private $urlLocators; + + /** + * @param CustomUrlLocatorInterface[] $urlLocators + */ + public function __construct(array $urlLocators = []) + { + $this->urlLocators = $urlLocators; + } + + /** + * @inheritdoc + */ + public function locateUrl($urlKey): ?string + { + foreach ($this->urlLocators as $urlLocator) { + $url = $urlLocator->locateUrl($urlKey); + if ($url !== null) { + return $url; + } + } + return null; + } +} diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolverInterface.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlLocatorInterface.php similarity index 84% rename from app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolverInterface.php rename to app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlLocatorInterface.php index 1aee63b670635..df0c0ee96c16c 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolverInterface.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlLocatorInterface.php @@ -12,7 +12,7 @@ * * It can be used, for example, to resolve '\' URL path to a 'Home' page. */ -interface CustomUrlResolverInterface +interface CustomUrlLocatorInterface { /** * Resolve URL based on custom rules. @@ -20,5 +20,5 @@ interface CustomUrlResolverInterface * @param string $urlKey * @return string|null Return null if URL cannot be resolved */ - public function resolveUrl($urlKey): ?string; + public function locateUrl($urlKey): ?string; } diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolver.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolver.php deleted file mode 100644 index 08efb54bd6bbb..0000000000000 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite/CustomUrlResolver.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite; - -/** - * Pool of custom URL resolvers. - */ -class CustomUrlResolver implements CustomUrlResolverInterface -{ - /** - * @var CustomUrlResolverInterface[] - */ - private $urlResolvers; - - /** - * @param CustomUrlResolverInterface[] $urlResolvers - */ - public function __construct(array $urlResolvers = []) - { - $this->urlResolvers = $urlResolvers; - } - - /** - * @inheritdoc - */ - public function resolveUrl($urlKey): ?string - { - foreach ($this->urlResolvers as $urlResolver) { - $url = $urlResolver->resolveUrl($urlKey); - if ($url !== null) { - return $url; - } - } - return null; - } -} diff --git a/app/code/Magento/UrlRewriteGraphQl/etc/di.xml b/app/code/Magento/UrlRewriteGraphQl/etc/di.xml index c7b1533962af0..a9865db4e97e8 100644 --- a/app/code/Magento/UrlRewriteGraphQl/etc/di.xml +++ b/app/code/Magento/UrlRewriteGraphQl/etc/di.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> - <preference for="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolverInterface" type="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlResolver"/> + <preference for="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface" type="Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocator"/> </config> From 54612e64fc73ffad12cd099b67df9ed6928bfabf Mon Sep 17 00:00:00 2001 From: Ian Meron <imeron@magento.com> Date: Wed, 30 May 2018 13:36:25 -0500 Subject: [PATCH 0869/2023] MQE-987: Decouple MFTF from Magento - replace all framework command references with bin/mftf references --- composer.json | 7 + composer.lock | 2424 +++++++++++++++-- dev/tests/acceptance/.env.example | 37 - dev/tests/acceptance/LICENSE.txt | 48 - dev/tests/acceptance/LICENSE_AFL.txt | 48 - dev/tests/acceptance/README.md | 64 - dev/tests/acceptance/RoboFile.php | 229 +- dev/tests/acceptance/codeception.dist.yml | 35 - dev/tests/acceptance/composer.json | 13 +- dev/tests/acceptance/composer.lock | 1201 +------- dev/tests/acceptance/pre-install.php | 395 --- dev/tests/acceptance/tests/_bootstrap.php | 111 +- .../tests/functional.suite.dist.yml | 42 - .../tests/functional/_bootstrap.php | 8 - 14 files changed, 2361 insertions(+), 2301 deletions(-) delete mode 100644 dev/tests/acceptance/.env.example delete mode 100644 dev/tests/acceptance/LICENSE.txt delete mode 100644 dev/tests/acceptance/LICENSE_AFL.txt delete mode 100755 dev/tests/acceptance/README.md delete mode 100644 dev/tests/acceptance/codeception.dist.yml delete mode 100644 dev/tests/acceptance/pre-install.php delete mode 100644 dev/tests/acceptance/tests/functional.suite.dist.yml delete mode 100644 dev/tests/acceptance/tests/functional/_bootstrap.php diff --git a/composer.json b/composer.json index e2a89ae1207a7..db4d7b4128c1b 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,12 @@ "preferred-install": "dist", "sort-packages": true }, + "repositories": [ + { + "type": "git", + "url": "git@github.com:magento/magento2-functional-testing-framework.git" + } + ], "require": { "php": "~7.1.3||~7.2.0", "ext-ctype": "*", @@ -81,6 +87,7 @@ "zendframework/zend-view": "~2.10.0" }, "require-dev": { + "magento/magento2-functional-testing-framework": "dev-develop", "friendsofphp/php-cs-fixer": "~2.10.0", "lusitanian/oauth": "~0.8.10", "pdepend/pdepend": "2.5.2", diff --git a/composer.lock b/composer.lock index b104cf2929ba7..464bf79fe429a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "daacd8800615d44aa1af0ac06c1ecc46", + "content-hash": "cafb3927f4eee0965f3abed6c3adb103", "packages": [ { "name": "braintree/braintree_php", @@ -837,13 +837,6 @@ "reference": "68522e5768edc8e829d1f64b620a3de3753f1141", "shasum": "" }, - "archive": { - "exclude": [ - "/demos", - "/documentation", - "/tests" - ] - }, "require": { "php": ">=5.2.11" }, @@ -862,6 +855,7 @@ "Zend_": "library/" } }, + "notification-url": "https://packagist.org/downloads/", "include-path": [ "library/" ], @@ -871,14 +865,10 @@ "description": "Magento Zend Framework 1", "homepage": "http://framework.zend.com/", "keywords": [ - "framework", - "zf1" + "ZF1", + "framework" ], - "support": { - "source": "https://github.com/magento-engcom/zf1-php-7.2-support/tree/master", - "issues": "https://github.com/magento-engcom/zf1-php-7.2-support/issues" - }, - "time": "2018-04-06T17:12:22+00:00" + "time": "2018-04-06T18:49:03+00:00" }, { "name": "monolog/monolog", @@ -4319,153 +4309,142 @@ ], "packages-dev": [ { - "name": "doctrine/annotations", - "version": "v1.6.0", + "name": "allure-framework/allure-codeception", + "version": "1.2.7", "source": { "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + "url": "https://github.com/allure-framework/allure-codeception.git", + "reference": "48598f4b4603b50b663bfe977260113a40912131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "url": "https://api.github.com/repos/allure-framework/allure-codeception/zipball/48598f4b4603b50b663bfe977260113a40912131", + "reference": "48598f4b4603b50b663bfe977260113a40912131", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^6.4" + "allure-framework/allure-php-api": "~1.1.0", + "codeception/codeception": "~2.1", + "php": ">=5.4.0", + "symfony/filesystem": ">=2.6", + "symfony/finder": ">=2.6" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + "psr-0": { + "Yandex": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "Apache-2.0" ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Ivan Krutov", + "email": "vania-pooh@yandex-team.ru", + "role": "Developer" } ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", + "description": "A Codeception adapter for Allure report.", + "homepage": "http://allure.qatools.ru/", "keywords": [ - "annotations", - "docblock", - "parser" - ], - "time": "2017-12-06T07:11:42+00:00" + "allure", + "attachments", + "cases", + "codeception", + "report", + "steps", + "testing" + ], + "time": "2018-03-07T11:18:27+00:00" }, { - "name": "doctrine/instantiator", - "version": "1.1.0", + "name": "allure-framework/allure-php-api", + "version": "1.1.4", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + "url": "https://github.com/allure-framework/allure-php-adapter-api.git", + "reference": "a462a0da121681577033e13c123b6cc4e89cdc64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "url": "https://api.github.com/repos/allure-framework/allure-php-adapter-api/zipball/a462a0da121681577033e13c123b6cc4e89cdc64", + "reference": "a462a0da121681577033e13c123b6cc4e89cdc64", "shasum": "" }, "require": { - "php": "^7.1" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "^6.2.3", - "squizlabs/php_codesniffer": "^3.0.2" + "jms/serializer": ">=0.16.0", + "moontoast/math": ">=1.1.0", + "php": ">=5.4.0", + "phpunit/phpunit": ">=4.0.0", + "ramsey/uuid": ">=3.0.0", + "symfony/http-foundation": ">=2.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "psr-0": { + "Yandex": [ + "src/", + "test/" + ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "Apache-2.0" ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "name": "Ivan Krutov", + "email": "vania-pooh@yandex-team.ru", + "role": "Developer" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "description": "PHP API for Allure adapter", + "homepage": "http://allure.qatools.ru/", "keywords": [ - "constructor", - "instantiate" + "allure", + "api", + "php", + "report" ], - "time": "2017-07-22T11:58:36+00:00" + "time": "2016-12-07T12:15:46+00:00" }, { - "name": "doctrine/lexer", - "version": "v1.0.1", + "name": "behat/gherkin", + "version": "v4.4.5", "source": { "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + "url": "https://github.com/Behat/Gherkin.git", + "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/5c14cff4f955b17d20d088dec1bde61c0539ec74", + "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "~4.5|~5", + "symfony/phpunit-bridge": "~2.7|~3", + "symfony/yaml": "~2.3|~3" + }, + "suggest": { + "symfony/yaml": "If you want to parse features, represented in YAML files" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "4.4-dev" } }, "autoload": { "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" + "Behat\\Gherkin": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4474,95 +4453,94 @@ ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" } ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "http://www.doctrine-project.org", + "description": "Gherkin DSL parser for PHP 5.3", + "homepage": "http://behat.org/", "keywords": [ - "lexer", + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", "parser" ], - "time": "2014-09-09T13:34:57+00:00" + "time": "2016-10-30T11:50:56+00:00" }, { - "name": "friendsofphp/php-cs-fixer", - "version": "v2.10.5", + "name": "codeception/codeception", + "version": "2.3.9", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "e49993dfb9b96ec8b8d9964c4627599b050a6e99" + "url": "https://github.com/Codeception/Codeception.git", + "reference": "104f46fa0bde339f1bcc3a375aac21eb36e65a1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/e49993dfb9b96ec8b8d9964c4627599b050a6e99", - "reference": "e49993dfb9b96ec8b8d9964c4627599b050a6e99", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/104f46fa0bde339f1bcc3a375aac21eb36e65a1e", + "reference": "104f46fa0bde339f1bcc3a375aac21eb36e65a1e", "shasum": "" }, "require": { - "composer/semver": "^1.4", - "doctrine/annotations": "^1.2", + "behat/gherkin": "~4.4.0", + "codeception/stub": "^1.0", "ext-json": "*", - "ext-tokenizer": "*", - "php": "^5.6 || >=7.0 <7.3", - "php-cs-fixer/diff": "^1.2", - "symfony/console": "^3.2 || ^4.0", - "symfony/event-dispatcher": "^3.0 || ^4.0", - "symfony/filesystem": "^3.0 || ^4.0", - "symfony/finder": "^3.0 || ^4.0", - "symfony/options-resolver": "^3.0 || ^4.0", - "symfony/polyfill-php70": "^1.0", - "symfony/polyfill-php72": "^1.4", - "symfony/process": "^3.0 || ^4.0", - "symfony/stopwatch": "^3.0 || ^4.0" - }, - "conflict": { - "hhvm": "*" + "ext-mbstring": "*", + "facebook/webdriver": ">=1.1.3 <2.0", + "guzzlehttp/guzzle": ">=4.1.4 <7.0", + "guzzlehttp/psr7": "~1.0", + "php": ">=5.4.0 <8.0", + "phpunit/php-code-coverage": ">=2.2.4 <6.0", + "phpunit/phpunit": ">=4.8.28 <5.0.0 || >=5.6.3 <7.0", + "sebastian/comparator": ">1.1 <3.0", + "sebastian/diff": ">=1.4 <3.0", + "symfony/browser-kit": ">=2.7 <5.0", + "symfony/console": ">=2.7 <5.0", + "symfony/css-selector": ">=2.7 <5.0", + "symfony/dom-crawler": ">=2.7 <5.0", + "symfony/event-dispatcher": ">=2.7 <5.0", + "symfony/finder": ">=2.7 <5.0", + "symfony/yaml": ">=2.7 <5.0" }, "require-dev": { - "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", - "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.0", - "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.0", - "php-cs-fixer/accessible-object": "^1.0", - "phpunit/phpunit": "^5.7.23 || ^6.4.3", - "phpunitgoodpractices/traits": "^1.3.1", - "symfony/phpunit-bridge": "^3.2.2 || ^4.0" + "codeception/specify": "~0.3", + "facebook/graph-sdk": "~5.3", + "flow/jsonpath": "~0.2", + "monolog/monolog": "~1.8", + "pda/pheanstalk": "~3.0", + "php-amqplib/php-amqplib": "~2.4", + "predis/predis": "^1.0", + "squizlabs/php_codesniffer": "~2.0", + "symfony/process": ">=2.7 <5.0", + "vlucas/phpdotenv": "^2.4.0" }, "suggest": { - "ext-mbstring": "For handling non-UTF8 characters in cache signature.", - "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + "aws/aws-sdk-php": "For using AWS Auth in REST module and Queue module", + "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests", + "codeception/specify": "BDD-style code blocks", + "codeception/verify": "BDD-style assertions", + "flow/jsonpath": "For using JSONPath in REST module", + "league/factory-muffin": "For DataFactory module", + "league/factory-muffin-faker": "For Faker support in DataFactory module", + "phpseclib/phpseclib": "for SFTP option in FTP Module", + "stecman/symfony-console-completion": "For BASH autocompletion", + "symfony/phpunit-bridge": "For phpunit-bridge support" }, "bin": [ - "php-cs-fixer" + "codecept" ], - "type": "application", + "type": "library", + "extra": { + "branch-alias": [] + }, "autoload": { "psr-4": { - "PhpCsFixer\\": "src/" - }, - "classmap": [ - "tests/Test/AbstractFixerTestCase.php", - "tests/Test/AbstractIntegrationCaseFactory.php", - "tests/Test/AbstractIntegrationTestCase.php", - "tests/Test/Assert/AssertTokensTrait.php", - "tests/Test/Constraint/SameStringsConstraint.php", - "tests/Test/IntegrationCase.php", - "tests/Test/IntegrationCaseFactory.php", - "tests/Test/IntegrationCaseFactoryInterface.php", - "tests/Test/InternalIntegrationCaseFactory.php", - "tests/TestCase.php" - ] + "Codeception\\": "src\\Codeception", + "Codeception\\Extension\\": "ext" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4570,55 +4548,92 @@ ], "authors": [ { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "http://codegyre.com" } ], - "description": "A tool to automatically fix PHP code style", - "time": "2018-03-20T18:07:08+00:00" + "description": "BDD-style testing framework", + "homepage": "http://codeception.com/", + "keywords": [ + "BDD", + "TDD", + "acceptance testing", + "functional testing", + "unit testing" + ], + "time": "2018-02-26T23:29:41+00:00" }, { - "name": "lusitanian/oauth", - "version": "v0.8.10", + "name": "codeception/stub", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/Lusitanian/PHPoAuthLib.git", - "reference": "09f4af38f17db6938253f4d1b171d537913ac1ed" + "url": "https://github.com/Codeception/Stub.git", + "reference": "95fb7a36b81890dd2e5163e7ab31310df6f1bb99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Lusitanian/PHPoAuthLib/zipball/09f4af38f17db6938253f4d1b171d537913ac1ed", - "reference": "09f4af38f17db6938253f4d1b171d537913ac1ed", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/95fb7a36b81890dd2e5163e7ab31310df6f1bb99", + "reference": "95fb7a36b81890dd2e5163e7ab31310df6f1bb99", "shasum": "" }, "require": { - "php": ">=5.3.0" + "phpunit/phpunit-mock-objects": ">2.3 <7.0" }, "require-dev": { - "phpunit/phpunit": "3.7.*", - "predis/predis": "0.8.*@dev", - "squizlabs/php_codesniffer": "2.*", - "symfony/http-foundation": "~2.1" + "phpunit/phpunit": ">=4.8 <8.0" }, - "suggest": { - "ext-openssl": "Allows for usage of secure connections with the stream-based HTTP client.", - "predis/predis": "Allows using the Redis storage backend.", - "symfony/http-foundation": "Allows using the Symfony Session storage backend." + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", + "time": "2018-02-18T13:56:56+00:00" + }, + { + "name": "consolidation/annotated-command", + "version": "2.8.3", + "source": { + "type": "git", + "url": "https://github.com/consolidation/annotated-command.git", + "reference": "8f8f5da2ca06fbd3a85f7d551c49f844b7c59437" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/8f8f5da2ca06fbd3a85f7d551c49f844b7c59437", + "reference": "8f8f5da2ca06fbd3a85f7d551c49f844b7c59437", + "shasum": "" + }, + "require": { + "consolidation/output-formatters": "^3.1.12", + "php": ">=5.4.0", + "psr/log": "^1", + "symfony/console": "^2.8|^3|^4", + "symfony/event-dispatcher": "^2.5|^3|^4", + "symfony/finder": "^2.5|^3|^4" + }, + "require-dev": { + "greg-1-anderson/composer-test-scenarios": "^1", + "phpunit/phpunit": "^4.8", + "satooshi/php-coveralls": "^1.0.2 | dev-master", + "squizlabs/php_codesniffer": "^2.7" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.1-dev" + "dev-master": "2.x-dev" } }, "autoload": { - "psr-0": { - "OAuth": "src", - "OAuth\\Unit": "tests" + "psr-4": { + "Consolidation\\AnnotatedCommand\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -4627,39 +4642,1592 @@ ], "authors": [ { - "name": "David Desberg", - "email": "david@daviddesberg.com" - }, - { - "name": "Elliot Chance", - "email": "elliotchance@gmail.com" - }, - { - "name": "Pieter Hordijk", - "email": "info@pieterhordijk.com" + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" } ], - "description": "PHP 5.3+ oAuth 1/2 Library", - "keywords": [ - "Authentication", - "authorization", - "oauth", - "security" - ], - "time": "2016-07-12T22:15:40+00:00" + "description": "Initialize Symfony Console commands from annotated command class methods.", + "time": "2018-02-23T16:32:04+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.7.0", + "name": "consolidation/config", + "version": "1.0.9", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "url": "https://github.com/consolidation/config.git", + "reference": "34ca8d7c1ee60a7b591b10617114cf1210a2e92c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/consolidation/config/zipball/34ca8d7c1ee60a7b591b10617114cf1210a2e92c", + "reference": "34ca8d7c1ee60a7b591b10617114cf1210a2e92c", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^1.1.0", + "grasmash/expander": "^1", + "php": ">=5.4.0" + }, + "require-dev": { + "greg-1-anderson/composer-test-scenarios": "^1", + "phpunit/phpunit": "^4", + "satooshi/php-coveralls": "^1.0", + "squizlabs/php_codesniffer": "2.*", + "symfony/console": "^2.5|^3|^4", + "symfony/yaml": "^2.8.11|^3|^4" + }, + "suggest": { + "symfony/yaml": "Required to use Consolidation\\Config\\Loader\\YamlConfigLoader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Consolidation\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Provide configuration services for a commandline tool.", + "time": "2017-12-22T17:28:19+00:00" + }, + { + "name": "consolidation/log", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/consolidation/log.git", + "reference": "dbc7c535f319a4a2d5a5077738f8eb7c10df8821" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/log/zipball/dbc7c535f319a4a2d5a5077738f8eb7c10df8821", + "reference": "dbc7c535f319a4a2d5a5077738f8eb7c10df8821", + "shasum": "" + }, + "require": { + "php": ">=5.5.0", + "psr/log": "~1.0", + "symfony/console": "^2.8|^3|^4" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "satooshi/php-coveralls": "dev-master", + "squizlabs/php_codesniffer": "2.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Consolidation\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.", + "time": "2017-11-29T01:44:16+00:00" + }, + { + "name": "consolidation/output-formatters", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/consolidation/output-formatters.git", + "reference": "da889e4bce19f145ca4ec5b1725a946f4eb625a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/da889e4bce19f145ca4ec5b1725a946f4eb625a9", + "reference": "da889e4bce19f145ca4ec5b1725a946f4eb625a9", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "symfony/console": "^2.8|^3|^4", + "symfony/finder": "^2.5|^3|^4" + }, + "require-dev": { + "g-1-a/composer-test-scenarios": "^2", + "phpunit/phpunit": "^5.7.27", + "satooshi/php-coveralls": "^2", + "squizlabs/php_codesniffer": "^2.7", + "symfony/console": "3.2.3", + "symfony/var-dumper": "^2.8|^3|^4", + "victorjonsson/markdowndocs": "^1.3" + }, + "suggest": { + "symfony/var-dumper": "For using the var_dump formatter" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Consolidation\\OutputFormatters\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Format text by applying transformations provided by plug-in formatters.", + "time": "2018-03-20T15:18:32+00:00" + }, + { + "name": "consolidation/robo", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/consolidation/Robo.git", + "reference": "54a13e268917b92576d75e10dca8227b95a574d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/Robo/zipball/54a13e268917b92576d75e10dca8227b95a574d9", + "reference": "54a13e268917b92576d75e10dca8227b95a574d9", + "shasum": "" + }, + "require": { + "consolidation/annotated-command": "^2.8.2", + "consolidation/config": "^1.0.1", + "consolidation/log": "~1", + "consolidation/output-formatters": "^3.1.13", + "grasmash/yaml-expander": "^1.3", + "league/container": "^2.2", + "php": ">=5.5.0", + "symfony/console": "^2.8|^3|^4", + "symfony/event-dispatcher": "^2.5|^3|^4", + "symfony/filesystem": "^2.5|^3|^4", + "symfony/finder": "^2.5|^3|^4", + "symfony/process": "^2.5|^3|^4" + }, + "replace": { + "codegyre/robo": "< 1.0" + }, + "require-dev": { + "codeception/aspect-mock": "^1|^2.1.1", + "codeception/base": "^2.3.7", + "codeception/verify": "^0.3.2", + "g-1-a/composer-test-scenarios": "^2", + "goaop/framework": "~2.1.2", + "goaop/parser-reflection": "^1.1.0", + "natxet/cssmin": "3.0.4", + "nikic/php-parser": "^3.1.5", + "patchwork/jsqueeze": "~2", + "pear/archive_tar": "^1.4.2", + "phpunit/php-code-coverage": "~2|~4", + "satooshi/php-coveralls": "^2", + "squizlabs/php_codesniffer": "^2.8" + }, + "suggest": { + "henrikbjorn/lurker": "For monitoring filesystem changes in taskWatch", + "natxet/CssMin": "For minifying CSS files in taskMinify", + "patchwork/jsqueeze": "For minifying JS files in taskMinify", + "pear/archive_tar": "Allows tar archives to be created and extracted in taskPack and taskExtract, respectively." + }, + "bin": [ + "robo" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev", + "dev-state": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Robo\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Davert", + "email": "davert.php@resend.cc" + } + ], + "description": "Modern task runner", + "time": "2018-04-06T05:27:37+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/3fbd874921ab2c041e899d044585a2ab9795df8a", + "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Dflydev\\DotAccessData": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "time": "2017-01-20T21:14:22+00:00" + }, + { + "name": "doctrine/annotations", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2017-12-06T07:11:42+00:00" + }, + { + "name": "doctrine/collections", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "~0.1@dev", + "phpunit/phpunit": "^5.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Collections\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Collections Abstraction library", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "array", + "collections", + "iterator" + ], + "time": "2017-07-22T10:37:32+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2017-07-22T11:58:36+00:00" + }, + { + "name": "doctrine/lexer", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "lexer", + "parser" + ], + "time": "2014-09-09T13:34:57+00:00" + }, + { + "name": "epfremme/swagger-php", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/epfremmer/swagger-php.git", + "reference": "eee28a442b7e6220391ec953d3c9b936354f23bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/epfremmer/swagger-php/zipball/eee28a442b7e6220391ec953d3c9b936354f23bc", + "reference": "eee28a442b7e6220391ec953d3c9b936354f23bc", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.2", + "doctrine/collections": "^1.3", + "jms/serializer": "^1.1", + "php": ">=5.5", + "phpoption/phpoption": "^1.1", + "symfony/yaml": "^2.7|^3.1" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "~4.8|~5.0", + "satooshi/php-coveralls": "^1.0" + }, + "type": "package", + "autoload": { + "psr-4": { + "Epfremme\\Swagger\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Edward Pfremmer", + "email": "epfremme@nerdery.com" + } + ], + "description": "Library for parsing swagger documentation into PHP entities for use in testing and code generation", + "time": "2016-09-26T17:24:17+00:00" + }, + { + "name": "facebook/webdriver", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/facebook/php-webdriver.git", + "reference": "86b5ca2f67173c9d34340845dd690149c886a605" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/86b5ca2f67173c9d34340845dd690149c886a605", + "reference": "86b5ca2f67173c9d34340845dd690149c886a605", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-zip": "*", + "php": "^5.6 || ~7.0", + "symfony/process": "^2.8 || ^3.1 || ^4.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.0", + "guzzle/guzzle": "^3.4.1", + "php-coveralls/php-coveralls": "^1.0.2", + "php-mock/php-mock-phpunit": "^1.1", + "phpunit/phpunit": "^5.7", + "sebastian/environment": "^1.3.4 || ^2.0 || ^3.0", + "squizlabs/php_codesniffer": "^2.6", + "symfony/var-dumper": "^3.3 || ^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-community": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "A PHP client for Selenium WebDriver", + "homepage": "https://github.com/facebook/php-webdriver", + "keywords": [ + "facebook", + "php", + "selenium", + "webdriver" + ], + "time": "2017-11-15T11:08:09+00:00" + }, + { + "name": "flow/jsonpath", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/FlowCommunications/JSONPath.git", + "reference": "f0222818d5c938e4ab668ab2e2c079bd51a27112" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FlowCommunications/JSONPath/zipball/f0222818d5c938e4ab668ab2e2c079bd51a27112", + "reference": "f0222818d5c938e4ab668ab2e2c079bd51a27112", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "peekmo/jsonpath": "dev-master", + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Flow\\JSONPath": "src/", + "Flow\\JSONPath\\Test": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephen Frank", + "email": "stephen@flowsa.com" + } + ], + "description": "JSONPath implementation for parsing, searching and flattening arrays", + "time": "2018-03-04T16:39:47+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v2.10.5", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "e49993dfb9b96ec8b8d9964c4627599b050a6e99" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/e49993dfb9b96ec8b8d9964c4627599b050a6e99", + "reference": "e49993dfb9b96ec8b8d9964c4627599b050a6e99", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4", + "doctrine/annotations": "^1.2", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^5.6 || >=7.0 <7.3", + "php-cs-fixer/diff": "^1.2", + "symfony/console": "^3.2 || ^4.0", + "symfony/event-dispatcher": "^3.0 || ^4.0", + "symfony/filesystem": "^3.0 || ^4.0", + "symfony/finder": "^3.0 || ^4.0", + "symfony/options-resolver": "^3.0 || ^4.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0", + "symfony/stopwatch": "^3.0 || ^4.0" + }, + "conflict": { + "hhvm": "*" + }, + "require-dev": { + "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", + "justinrainbow/json-schema": "^5.0", + "keradus/cli-executor": "^1.0", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.0", + "php-cs-fixer/accessible-object": "^1.0", + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "phpunitgoodpractices/traits": "^1.3.1", + "symfony/phpunit-bridge": "^3.2.2 || ^4.0" + }, + "suggest": { + "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationCaseFactory.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/Constraint/SameStringsConstraint.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php", + "tests/Test/IntegrationCaseFactoryInterface.php", + "tests/Test/InternalIntegrationCaseFactory.php", + "tests/TestCase.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "time": "2018-03-20T18:07:08+00:00" + }, + { + "name": "fzaninotto/faker", + "version": "v1.7.1", + "source": { + "type": "git", + "url": "https://github.com/fzaninotto/Faker.git", + "reference": "d3ed4cc37051c1ca52d22d76b437d14809fc7e0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/d3ed4cc37051c1ca52d22d76b437d14809fc7e0d", + "reference": "d3ed4cc37051c1ca52d22d76b437d14809fc7e0d", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "ext-intl": "*", + "phpunit/phpunit": "^4.0 || ^5.0", + "squizlabs/php_codesniffer": "^1.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "time": "2017-08-15T16:48:10+00:00" + }, + { + "name": "grasmash/expander", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/grasmash/expander.git", + "reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/grasmash/expander/zipball/95d6037344a4be1dd5f8e0b0b2571a28c397578f", + "reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^1.1.0", + "php": ">=5.4" + }, + "require-dev": { + "greg-1-anderson/composer-test-scenarios": "^1", + "phpunit/phpunit": "^4|^5.5.4", + "satooshi/php-coveralls": "^1.0.2|dev-master", + "squizlabs/php_codesniffer": "^2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Grasmash\\Expander\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Grasmick" + } + ], + "description": "Expands internal property references in PHP arrays file.", + "time": "2017-12-21T22:14:55+00:00" + }, + { + "name": "grasmash/yaml-expander", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/grasmash/yaml-expander.git", + "reference": "3f0f6001ae707a24f4d9733958d77d92bf9693b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/grasmash/yaml-expander/zipball/3f0f6001ae707a24f4d9733958d77d92bf9693b1", + "reference": "3f0f6001ae707a24f4d9733958d77d92bf9693b1", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^1.1.0", + "php": ">=5.4", + "symfony/yaml": "^2.8.11|^3|^4" + }, + "require-dev": { + "greg-1-anderson/composer-test-scenarios": "^1", + "phpunit/phpunit": "^4.8|^5.5.4", + "satooshi/php-coveralls": "^1.0.2|dev-master", + "squizlabs/php_codesniffer": "^2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Grasmash\\YamlExpander\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Grasmick" + } + ], + "description": "Expands internal property references in a yaml file.", + "time": "2017-12-16T16:06:03+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2018-04-22T15:46:56+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2017-03-20T17:10:46+00:00" + }, + { + "name": "jms/metadata", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/metadata.git", + "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/6a06970a10e0a532fb52d3959547123b84a3b3ab", + "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "doctrine/cache": "~1.0", + "symfony/cache": "~3.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-0": { + "Metadata\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Class/method/property metadata management in PHP", + "keywords": [ + "annotations", + "metadata", + "xml", + "yaml" + ], + "time": "2016-12-05T10:18:33+00:00" + }, + { + "name": "jms/parser-lib", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/parser-lib.git", + "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/parser-lib/zipball/c509473bc1b4866415627af0e1c6cc8ac97fa51d", + "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d", + "shasum": "" + }, + "require": { + "phpoption/phpoption": ">=0.9,<2.0-dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "JMS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "description": "A library for easily creating recursive-descent parsers.", + "time": "2012-11-18T18:08:43+00:00" + }, + { + "name": "jms/serializer", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/serializer.git", + "reference": "e7c53477ff55c21d1b1db7d062edc050a24f465f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/e7c53477ff55c21d1b1db7d062edc050a24f465f", + "reference": "e7c53477ff55c21d1b1db7d062edc050a24f465f", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/instantiator": "^1.0.3", + "jms/metadata": "~1.1", + "jms/parser-lib": "1.*", + "php": "^5.5|^7.0", + "phpcollection/phpcollection": "~0.1", + "phpoption/phpoption": "^1.1" + }, + "conflict": { + "twig/twig": "<1.12" + }, + "require-dev": { + "doctrine/orm": "~2.1", + "doctrine/phpcr-odm": "^1.3|^2.0", + "ext-pdo_sqlite": "*", + "jackalope/jackalope-doctrine-dbal": "^1.1.5", + "phpunit/phpunit": "^4.8|^5.0", + "propel/propel1": "~1.7", + "psr/container": "^1.0", + "symfony/dependency-injection": "^2.7|^3.3|^4.0", + "symfony/expression-language": "^2.6|^3.0", + "symfony/filesystem": "^2.1", + "symfony/form": "~2.1|^3.0", + "symfony/translation": "^2.1|^3.0", + "symfony/validator": "^2.2|^3.0", + "symfony/yaml": "^2.1|^3.0", + "twig/twig": "~1.12|~2.0" + }, + "suggest": { + "doctrine/cache": "Required if you like to use cache functionality.", + "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.", + "symfony/yaml": "Required if you'd like to serialize data to YAML format." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.11-dev" + } + }, + "autoload": { + "psr-0": { + "JMS\\Serializer": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + }, + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.", + "homepage": "http://jmsyst.com/libs/serializer", + "keywords": [ + "deserialization", + "jaxb", + "json", + "serialization", + "xml" + ], + "time": "2018-02-04T17:48:54+00:00" + }, + { + "name": "league/container", + "version": "2.4.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/container.git", + "reference": "43f35abd03a12977a60ffd7095efd6a7808488c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/container/zipball/43f35abd03a12977a60ffd7095efd6a7808488c0", + "reference": "43f35abd03a12977a60ffd7095efd6a7808488c0", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.2", + "php": "^5.4.0 || ^7.0" + }, + "provide": { + "container-interop/container-interop-implementation": "^1.2", + "psr/container-implementation": "^1.0" + }, + "replace": { + "orno/di": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Container\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Phil Bennett", + "email": "philipobenito@gmail.com", + "homepage": "http://www.philipobenito.com", + "role": "Developer" + } + ], + "description": "A fast and intuitive dependency injection container.", + "homepage": "https://github.com/thephpleague/container", + "keywords": [ + "container", + "dependency", + "di", + "injection", + "league", + "provider", + "service" + ], + "time": "2017-05-10T09:20:27+00:00" + }, + { + "name": "lusitanian/oauth", + "version": "v0.8.10", + "source": { + "type": "git", + "url": "https://github.com/Lusitanian/PHPoAuthLib.git", + "reference": "09f4af38f17db6938253f4d1b171d537913ac1ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Lusitanian/PHPoAuthLib/zipball/09f4af38f17db6938253f4d1b171d537913ac1ed", + "reference": "09f4af38f17db6938253f4d1b171d537913ac1ed", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*", + "predis/predis": "0.8.*@dev", + "squizlabs/php_codesniffer": "2.*", + "symfony/http-foundation": "~2.1" + }, + "suggest": { + "ext-openssl": "Allows for usage of secure connections with the stream-based HTTP client.", + "predis/predis": "Allows using the Redis storage backend.", + "symfony/http-foundation": "Allows using the Symfony Session storage backend." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + }, + "autoload": { + "psr-0": { + "OAuth": "src", + "OAuth\\Unit": "tests" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David Desberg", + "email": "david@daviddesberg.com" + }, + { + "name": "Elliot Chance", + "email": "elliotchance@gmail.com" + }, + { + "name": "Pieter Hordijk", + "email": "info@pieterhordijk.com" + } + ], + "description": "PHP 5.3+ oAuth 1/2 Library", + "keywords": [ + "Authentication", + "authorization", + "oauth", + "security" + ], + "time": "2016-07-12T22:15:40+00:00" + }, + { + "name": "magento/magento2-functional-testing-framework", + "version": "dev-develop", + "source": { + "type": "git", + "url": "git@github.com:magento/magento2-functional-testing-framework.git", + "reference": "343009b056b11d8836e132221d72aab8fafa039f" + }, + "require": { + "allure-framework/allure-codeception": "~1.2.6", + "codeception/codeception": "~2.3.4", + "consolidation/robo": "^1.0.0", + "epfremme/swagger-php": "^2.0", + "flow/jsonpath": ">0.2", + "fzaninotto/faker": "^1.6", + "mustache/mustache": "~2.5", + "php": "7.0.2|7.0.4|~7.0.6|~7.1.0|~7.2.0", + "symfony/process": "^2.8 || ^3.1 || ^4.0", + "vlucas/phpdotenv": "^2.4" + }, + "require-dev": { + "brainmaestro/composer-git-hooks": "^2.3", + "codacy/coverage": "^1.4", + "codeception/aspect-mock": "^3.0", + "doctrine/cache": "<1.7.0", + "goaop/framework": "2.2.0", + "php-coveralls/php-coveralls": "^1.0", + "phpmd/phpmd": "^2.6.0", + "rregeer/phpunit-coverage-check": "^0.1.4", + "sebastian/phpcpd": "~3.0", + "squizlabs/php_codesniffer": "1.5.3", + "symfony/stopwatch": "~3.4.6" + }, + "bin": [ + "bin/mftf" + ], + "type": "library", + "extra": { + "hooks": { + "pre-push": "bin/all-checks" + } + }, + "autoload": { + "files": [ + "src/Magento/FunctionalTestingFramework/_bootstrap.php" + ], + "psr-4": { + "Magento\\FunctionalTestingFramework\\": "src/Magento/FunctionalTestingFramework", + "MFTF\\": "dev/tests/functional/MFTF" + } + }, + "autoload-dev": { + "psr-4": { + "tests\\unit\\": "dev/tests/unit" + } + }, + "scripts": { + "tests": [ + "bin/phpunit-checks" + ], + "static": [ + "bin/static-checks" + ] + }, + "license": [ + "AGPL-3.0" + ], + "description": "Magento2 Functional Testing Framework", + "keywords": [ + "automation", + "functional", + "magento", + "testing" + ], + "time": "2018-05-30T15:36:22+00:00" + }, + { + "name": "moontoast/math", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/ramsey/moontoast-math.git", + "reference": "c2792a25df5cad4ff3d760dd37078fc5b6fccc79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/moontoast-math/zipball/c2792a25df5cad4ff3d760dd37078fc5b6fccc79", + "reference": "c2792a25df5cad4ff3d760dd37078fc5b6fccc79", + "shasum": "" + }, + "require": { + "ext-bcmath": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "jakub-onderka/php-parallel-lint": "^0.9.0", + "phpunit/phpunit": "^4.7|>=5.0 <5.4", + "satooshi/php-coveralls": "^0.6.1", + "squizlabs/php_codesniffer": "^2.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Moontoast\\Math\\": "src/Moontoast/Math/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A mathematics library, providing functionality for large numbers", + "homepage": "https://github.com/ramsey/moontoast-math", + "keywords": [ + "bcmath", + "math" + ], + "time": "2017-02-16T16:54:46+00:00" + }, + { + "name": "mustache/mustache", + "version": "v2.12.0", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/mustache.php.git", + "reference": "fe8fe72e9d580591854de404cc59a1b83ca4d19e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/fe8fe72e9d580591854de404cc59a1b83ca4d19e", + "reference": "fe8fe72e9d580591854de404cc59a1b83ca4d19e", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~1.11", + "phpunit/phpunit": "~3.7|~4.0|~5.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Mustache": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "A Mustache implementation in PHP.", + "homepage": "https://github.com/bobthecow/mustache.php", + "keywords": [ + "mustache", + "templating" + ], + "time": "2017-07-11T12:54:05+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", "shasum": "" }, "require": { @@ -4886,6 +6454,54 @@ ], "time": "2018-02-15T16:58:55+00:00" }, + { + "name": "phpcollection/phpcollection", + "version": "0.5.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-collection.git", + "reference": "f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6", + "reference": "f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6", + "shasum": "" + }, + "require": { + "phpoption/phpoption": "1.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.4-dev" + } + }, + "autoload": { + "psr-0": { + "PhpCollection": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "General-Purpose Collection Library for PHP", + "keywords": [ + "collection", + "list", + "map", + "sequence", + "set" + ], + "time": "2015-05-17T12:39:23+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", @@ -5102,7 +6718,57 @@ "phpmd", "pmd" ], - "time": "2017-01-20T14:41:10+00:00" + "time": "2017-01-20T14:41:10+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/94e644f7d2051a5f0fcf77d81605f152eecff0ed", + "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-0": { + "PhpOption\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "time": "2015-07-25T16:39:46+00:00" }, { "name": "phpspec/prophecy", @@ -6258,6 +7924,63 @@ ], "time": "2017-12-19T21:44:46+00:00" }, + { + "name": "symfony/browser-kit", + "version": "v4.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "c43bfa0182363b3fd64331b5e64e467349ff4670" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/c43bfa0182363b3fd64331b5e64e467349ff4670", + "reference": "c43bfa0182363b3fd64331b5e64e467349ff4670", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/dom-crawler": "~3.4|~4.0" + }, + "require-dev": { + "symfony/css-selector": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "https://symfony.com", + "time": "2018-03-19T22:35:49+00:00" + }, { "name": "symfony/config", "version": "v4.0.8", @@ -6320,6 +8043,59 @@ "homepage": "https://symfony.com", "time": "2018-03-19T22:35:49+00:00" }, + { + "name": "symfony/css-selector", + "version": "v4.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "03f965583147957f1ecbad7ea1c9d6fd5e525ec2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/03f965583147957f1ecbad7ea1c9d6fd5e525ec2", + "reference": "03f965583147957f1ecbad7ea1c9d6fd5e525ec2", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com", + "time": "2018-03-19T22:35:49+00:00" + }, { "name": "symfony/dependency-injection", "version": "v4.0.8", @@ -6391,6 +8167,115 @@ "homepage": "https://symfony.com", "time": "2018-04-02T09:52:41+00:00" }, + { + "name": "symfony/dom-crawler", + "version": "v4.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "d6c04c7532535b5e0b63db45b543cd60818e0fbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/d6c04c7532535b5e0b63db45b543cd60818e0fbc", + "reference": "d6c04c7532535b5e0b63db45b543cd60818e0fbc", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~3.4|~4.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2018-03-19T22:35:49+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v4.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "014487772c22d893168e5d628a13e882009fea29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/014487772c22d893168e5d628a13e882009fea29", + "reference": "014487772c22d893168e5d628a13e882009fea29", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "symfony/expression-language": "~3.4|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2018-04-30T01:05:59+00:00" + }, { "name": "symfony/options-resolver", "version": "v4.0.8", @@ -6608,6 +8493,64 @@ "homepage": "https://symfony.com", "time": "2018-02-19T16:50:22+00:00" }, + { + "name": "symfony/yaml", + "version": "v3.4.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "033cfa61ef06ee0847e056e530201842b6e926c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/033cfa61ef06ee0847e056e530201842b6e926c3", + "reference": "033cfa61ef06ee0847e056e530201842b6e926c3", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2018-04-08T08:21:29+00:00" + }, { "name": "theseer/fdomdocument", "version": "1.6.6", @@ -6688,6 +8631,56 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "time": "2017-04-07T12:08:54+00:00" }, + { + "name": "vlucas/phpdotenv", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause-Attribution" + ], + "authors": [ + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "http://www.vancelucas.com" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2016-09-01T10:05:43+00:00" + }, { "name": "webmozart/assert", "version": "1.3.0", @@ -6742,6 +8735,7 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { + "magento/magento2-functional-testing-framework": 20, "phpmd/phpmd": 0 }, "prefer-stable": true, diff --git a/dev/tests/acceptance/.env.example b/dev/tests/acceptance/.env.example deleted file mode 100644 index 432851acbf286..0000000000000 --- a/dev/tests/acceptance/.env.example +++ /dev/null @@ -1,37 +0,0 @@ -#Copyright © Magento, Inc. All rights reserved. -#See COPYING.txt for license details. - -#*** Set the base URL for your Magento instance ***# -MAGENTO_BASE_URL= - -#*** Set the Admin Username and Password for your Magento instance ***# -MAGENTO_BACKEND_NAME= -MAGENTO_ADMIN_USERNAME= -MAGENTO_ADMIN_PASSWORD= - -#*** Path to CLI entry point and command parameter name. Uncomment and change if folder structure differs from standard Magento installation -#MAGENTO_CLI_COMMAND_PATH=dev/tests/acceptance/utils/command.php -#MAGENTO_CLI_COMMAND_PARAMETER=command - -#*** Selenium Server Protocol, Host, Port, and Path, with local defaults. Uncomment and change if not running Selenium locally. -#SELENIUM_HOST=127.0.0.1 -#SELENIUM_PORT=4444 -#SELENIUM_PROTOCOL=http -#SELENIUM_PATH=/wd/hub - -#*** Uncomment and set host & port if your dev environment needs different value other than MAGENTO_BASE_URL for Rest API Requests ***# -#MAGENTO_RESTAPI_SERVER_HOST= -#MAGENTO_RESTAPI_SERVER_PORT= - -#*** Uncomment these properties to set up a dev environment with symlinked projects ***# -#TESTS_BP= -#FW_BP= -#TESTS_MODULE_PATH= - -#*** These properties impact the modules loaded into MFTF, you can point to your own full path, or a custom set of modules located with the core set -MODULE_WHITELIST=Magento_Framework,Magento_ConfigurableProductWishlist,Magento_ConfigurableProductCatalogSearch -#CUSTOM_MODULE_PATHS= - -#*** Bool property which allows the user to toggle debug output during test execution -#MFTF_DEBUG= -#*** End of .env ***# diff --git a/dev/tests/acceptance/LICENSE.txt b/dev/tests/acceptance/LICENSE.txt deleted file mode 100644 index 49525fd99da9c..0000000000000 --- a/dev/tests/acceptance/LICENSE.txt +++ /dev/null @@ -1,48 +0,0 @@ - -Open Software License ("OSL") v. 3.0 - -This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: - -Licensed under the Open Software License version 3.0 - - 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: - - 1. to reproduce the Original Work in copies, either alone or as part of a collective work; - - 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; - - 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; - - 4. to perform the Original Work publicly; and - - 5. to display the Original Work publicly. - - 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. - - 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. - - 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. - - 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). - - 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. - - 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. - - 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. - - 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). - - 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. - - 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. - - 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. - - 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. - - 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. - - 16. Modification of This License. This License is Copyright (C) 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under <insert your license name here>" or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. \ No newline at end of file diff --git a/dev/tests/acceptance/LICENSE_AFL.txt b/dev/tests/acceptance/LICENSE_AFL.txt deleted file mode 100644 index f39d641b18a19..0000000000000 --- a/dev/tests/acceptance/LICENSE_AFL.txt +++ /dev/null @@ -1,48 +0,0 @@ - -Academic Free License ("AFL") v. 3.0 - -This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: - -Licensed under the Academic Free License version 3.0 - - 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: - - 1. to reproduce the Original Work in copies, either alone or as part of a collective work; - - 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; - - 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, under any license of your choice that does not contradict the terms and conditions, including Licensor's reserved rights and remedies, in this Academic Free License; - - 4. to perform the Original Work publicly; and - - 5. to display the Original Work publicly. - - 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. - - 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. - - 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. - - 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). - - 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. - - 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. - - 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. - - 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). - - 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. - - 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. - - 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. - - 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. - - 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. - - 16. Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Academic Free License" or "AFL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under <insert your license name here>" or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. diff --git a/dev/tests/acceptance/README.md b/dev/tests/acceptance/README.md deleted file mode 100755 index 6350b9cabcdfa..0000000000000 --- a/dev/tests/acceptance/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# Magento Functional Testing Framework - ----- - -## System Requirements -[Magento Functional Testing Framework system requirements](http://devdocs.magento.com/guides/v2.2/magento-functional-testing-framework/getting-started.html#prepare-environment) - -## Installation -To install the Magento Functional Testing Framework, see [Getting Started](http://devdocs.magento.com/guides/v2.2/magento-functional-testing-framework/getting-started.html) - -## Contributing -Contributions can take the form of new components or features, changes to existing features, tests, documentation (such as developer guides, user guides, examples, or specifications), bug fixes, optimizations, or just good suggestions. - -To learn about how to make a contribution, click [here][1]. - -To open an issue, click [here][2]. - -To suggest documentation improvements, click [here][3]. - -[1]: <http://devdocs.magento.com/guides/v2.2/magento-functional-testing-framework/contribution-guidelines.html> -[2]: <https://github.com/magento/magento2-functional-testing-framework/issues> -[3]: <http://devdocs.magento.com> - -### Labels applied by the MFTF team - -Refer to the tables with descriptions of each label below. These labels are applied by the MFTF development team to community contributed issues and pull requests, to communicate status, impact, or which team is working on it. - -### Pull Request Status - -Label| Description ----|--- -**accept**| The pull request has been accepted and will be merged into mainline code. -**reject**| The pull request has been rejected and will not be merged into mainline code. Possible reasons can include but are not limited to: issue has already been fixed in another code contribution, or there is an issue with the code contribution. -**needsUpdate**| The Magento Team needs additional information from the reporter to properly prioritize and process the pull request. - -### Issue Resolution Status - -Label| Description ----|--- -**acknowledged**| The Magento Team has validated the issue and an internal ticket has been created. -**needsUpdate**| The Magento Team needs additional information from the reporter to properly prioritize and process the issue or pull request. -**cannot reproduce**| The Magento Team has not confirmed that this issue contains the minimum required information to reproduce. -**non-issue**| The Magento Team has not recognised any issue according to provided information. - -### Domains Impacted - -Label| Description ----|--- -**PROD**| Affects the Product team (mostly feature requests or business logic change). -**DOC**| Affects Documentation domain. -**TECH**| Affects Architect Group (mostly to make decisions around technology changes). - -### Type - -Label| Description ----|--- -**bugfix**| The issue or pull request relates to bug fixing. -**enhancement**| The issue or pull request that raises the MFTF to a higher degree (for example new features, optimization, refactoring, etc). - -## License - -Each Magento source file included in this distribution is licensed under APL 3.0 - -Please see LICENSE_APL3.txt for the full text of the APL 3.0 license or contact license@magentocommerce.com for a copy. diff --git a/dev/tests/acceptance/RoboFile.php b/dev/tests/acceptance/RoboFile.php index dd84b4131e502..f36150ad254b5 100644 --- a/dev/tests/acceptance/RoboFile.php +++ b/dev/tests/acceptance/RoboFile.php @@ -15,84 +15,6 @@ class RoboFile extends \Robo\Tasks { use Robo\Task\Base\loadShortcuts; - public function __construct() - { - require 'tests'. DIRECTORY_SEPARATOR . 'functional' . DIRECTORY_SEPARATOR . '_bootstrap.php'; - define('VENDOR_BIN_PATH', PROJECT_ROOT . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR); - - } - /** - * Duplicate the Example configuration files used to customize the Project for customization. - * - * @return void - */ - function cloneFiles() - { - $this->_exec('cp -vn .env.example .env'); - $this->_exec('cp -vf codeception.dist.yml codeception.yml'); - $this->_exec('cp -vf tests'. DIRECTORY_SEPARATOR .'functional.suite.dist.yml tests'. DIRECTORY_SEPARATOR .'functional.suite.yml'); - } - - /** - * Finds relative paths between codeception.yml file and MFTF path, and overwrites the default paths. - * - * @return void - */ - private function buildCodeceptionPaths() - { - $relativePathFunc = function ($from, $to) - { - $from = is_dir($from) ? rtrim($from, '\/') . '/' : $from; - $to = is_dir($to) ? rtrim($to, '\/') . '/' : $to; - $from = str_replace('\\', '/', $from); - $to = str_replace('\\', '/', $to); - - $from = explode('/', $from); - $to = explode('/', $to); - $relPath = $to; - - foreach($from as $depth => $dir) { - // find first non-matching dir - if($dir === $to[$depth]) { - // ignore this directory - array_shift($relPath); - } else { - // get number of remaining dirs to $from - $remaining = count($from) - $depth; - if($remaining > 1) { - // add traversals up to first matching dir - $padLength = (count($relPath) + $remaining - 1) * -1; - $relPath = array_pad($relPath, $padLength, '..'); - break; - } else { - $relPath[0] = './' . $relPath[0]; - } - } - } - return implode('/', $relPath); - }; - - //Find travel path from codeception.yml to FW_BP - $configYmlPath = dirname(dirname(TESTS_BP)) . DIRECTORY_SEPARATOR; - $relativePath = call_user_func($relativePathFunc, $configYmlPath, FW_BP); - $configYmlFile = $configYmlPath . "codeception.yml"; - $defaultConfigYmlFile = $configYmlPath . "codeception.dist.yml"; - - if (file_exists($configYmlFile)) { - $ymlContents = file_get_contents($configYmlFile); - } else { - $ymlContents = file_get_contents($defaultConfigYmlFile); - } - $ymlArray = Yaml::parse($ymlContents) ?? []; - if (!array_key_exists("paths", $ymlArray)) { - $ymlArray["paths"] = []; - } - $ymlArray["paths"]["support"] = $relativePath . 'src/Magento/FunctionalTestingFramework'; - $ymlArray["paths"]["envs"] = $relativePath . 'etc/_envs'; - $ymlText = Yaml::dump($ymlArray, 10); - file_put_contents($configYmlFile, $ymlText); - } - /** * Duplicate the Example configuration files for the Project. * Build the Codeception project. @@ -101,9 +23,7 @@ private function buildCodeceptionPaths() */ function buildProject() { - $this->cloneFiles(); - $this->buildCodeceptionPaths(); - $this->_exec(VENDOR_BIN_PATH .'codecept build'); + passthru($this->getBaseCmd("build:project")); } /** @@ -117,93 +37,26 @@ function generateTests(array $tests, $opts = [ 'config' => null, 'force' => false, 'nodes' => null, - 'lines' => 500, + 'lines' => null, 'tests' => null ]) { - require 'tests'. DIRECTORY_SEPARATOR . 'functional' . DIRECTORY_SEPARATOR . '_bootstrap.php'; - $testConfiguration = $this->createTestConfiguration($tests, $opts); - - // maintain backwards compatability for devops by not removing the nodes option yet - $lines = $opts['lines']; - - // create our manifest file here - $testManifest = \Magento\FunctionalTestingFramework\Util\Manifest\TestManifestFactory::makeManifest($opts['config'],$testConfiguration['suites']); - \Magento\FunctionalTestingFramework\Util\TestGenerator::getInstance(null, $testConfiguration['tests'])->createAllTestFiles($testManifest); - - if ($opts['config'] == 'parallel') { - $testManifest->createTestGroups($lines); - } - - \Magento\FunctionalTestingFramework\Suite\SuiteGenerator::getInstance()->generateAllSuites($testManifest); - $testManifest->generate(); - - $this->say("Generate Tests Command Run"); - } - - - /** - * Function which builds up a configuration including test and suites for consumption of Magento generation methods. - * - * @param array $tests - * @param array $opts - * @return array - */ - private function createTestConfiguration($tests, $opts) - { - // set our application configuration so we can references the user options in our framework - Magento\FunctionalTestingFramework\Config\MftfApplicationConfig::create( - $opts['force'], - Magento\FunctionalTestingFramework\Config\MftfApplicationConfig::GENERATION_PHASE, - $opts['verbose'] - ); + $baseCmd = $this->getBaseCmd("generate:tests"); - $testConfiguration = []; - $testConfiguration['tests'] = $tests; - $testConfiguration['suites'] = []; - - $testConfiguration = $this->parseTestsConfigJson($opts['tests'], $testConfiguration); - - // if we have references to specific tests, we resolve the test objects and pass them to the config - if (!empty($testConfiguration['tests'])) - { - $testObjects = []; - - foreach ($testConfiguration['tests'] as $test) - { - $testObjects[$test] = Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler::getInstance()->getObject($test); + $mftfArgNames = ['config', 'nodes', 'lines', 'tests']; + // append arguments to the end of the command + foreach ($opts as $argName => $argValue) { + if (in_array($argName, $mftfArgNames) && $argValue !== null) { + $baseCmd .= " --$argName $argValue"; } - - $testConfiguration['tests'] = $testObjects; } - return $testConfiguration; - } - - /** - * Function which takes a json string of potential custom configuration and parses/validates the resulting json - * passed in by the user. The result is a testConfiguration array. - * - * @param string $json - * @param array $testConfiguration - * @return array - */ - private function parseTestsConfigJson($json, $testConfiguration) { - if ($json == null) { - return $testConfiguration; + // use a separate conditional for the force flag (casting bool to string in php is hard) + if ($opts['force']) { + $baseCmd .= ' --force'; } - $jsonTestConfiguration = []; - $testConfigArray = json_decode($json, true); - - // stop execution if we have failed to properly parse any json - if (json_last_error() != JSON_ERROR_NONE) { - throw new \Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException("JSON could not be parsed: " . json_last_error_msg()); - } - - $jsonTestConfiguration['tests'] = $testConfigArray['tests'] ?? null;; - $jsonTestConfiguration['suites'] = $testConfigArray['suites'] ?? null; - return $jsonTestConfiguration; + $this->taskExec($baseCmd)->args($tests)->run(); } /** @@ -218,54 +71,21 @@ function generateSuite(array $args) if (empty($args)) { throw new Exception("Please provide suite name(s) after generate:suite command"); } - - $sg = \Magento\FunctionalTestingFramework\Suite\SuiteGenerator::getInstance(); - - foreach ($args as $arg) { - $sg->generateSuite($arg); - } - } - - /** - * Run all Functional tests. - * - * @return void - */ - function functional() - { - $this->_exec(VENDOR_BIN_PATH . 'codecept run functional'); + $baseCmd = $this->getBaseCmd("generate:suite"); + $this->taskExec($baseCmd)->args($args)->run(); } /** * Run all Tests with the specified @group tag'. * - * @param string $args - * @return void - */ - function group($args = '') - { - $this->taskExec(VENDOR_BIN_PATH . 'codecept run functional --verbose --steps --group')->args($args)->run(); - } - - /** - * Run all Functional tests located under the Directory Path provided. - * - * @param string $args - * @return void - */ - function folder($args = '') - { - $this->taskExec(VENDOR_BIN_PATH . 'codecept run functional')->args($args)->run(); - } - - /** - * Run all Tests marked with the @group tag 'example'. - * + * @param array $args * @return void */ - function example() + function group(array $args) { - $this->_exec(VENDOR_BIN_PATH . 'codecept run --group example'); + $args = array_merge($args, ['-k']); + $baseCmd = $this->getBaseCmd("run:group"); + $this->taskExec($baseCmd)->args($args)->run(); } /** @@ -337,12 +157,15 @@ function allure2Report() } /** - * Run the Pre-Install system check script. + * Private function for returning the formatted command for the passthru to mftf bin execution. * - * @return void + * @param string $command + * @return string */ - function preInstall() + private function getBaseCmd($command) { - $this->_exec('php pre-install.php'); + $this->writeln("\033[01;31m Use of robo will be deprecated with next major release, please use <root>/vendor/bin/mftf $command \033[0m"); + chdir(__DIR__); + return realpath('../../../vendor/bin/mftf') . " $command"; } } diff --git a/dev/tests/acceptance/codeception.dist.yml b/dev/tests/acceptance/codeception.dist.yml deleted file mode 100644 index 683edcb107fd1..0000000000000 --- a/dev/tests/acceptance/codeception.dist.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright © Magento, Inc. All rights reserved. -# See COPYING.txt for license details. -actor: Tester -paths: - tests: tests - log: tests/_output - data: tests/_data - support: "%REPLACED IN BUILD:PROJECT%" - envs: "%REPLACED IN BUILD:PROJECT%" -settings: - bootstrap: _bootstrap.php - colors: true - memory_limit: 1024M -extensions: - enabled: - - Codeception\Extension\RunFailed - - Magento\FunctionalTestingFramework\Extension\TestContextExtension - - Magento\FunctionalTestingFramework\Allure\Adapter\MagentoAllureAdapter - config: - Yandex\Allure\Adapter\AllureAdapter: - deletePreviousResults: true - outputDirectory: allure-results - ignoredAnnotations: - - env - - zephyrId - - useCaseId -params: - - .env -modules: - config: - Db: - dsn: "%DB_DSN%" - user: "%DB_USERNAME%" - password: "%DB_PASSWORD%" - dump: tests/_data/dump.sql \ No newline at end of file diff --git a/dev/tests/acceptance/composer.json b/dev/tests/acceptance/composer.json index 787d2579e03ca..a20176a29c4c8 100755 --- a/dev/tests/acceptance/composer.json +++ b/dev/tests/acceptance/composer.json @@ -9,20 +9,17 @@ "config": { "sort-packages": true }, - "repositories": [ - { - "type": "git", - "url": "git@github.com:magento/magento2-functional-testing-framework.git" - } - ], "require": { "php": "~7.1.3||~7.2.0", - "magento/magento2-functional-testing-framework": "~2.2.0" + "codeception/codeception": "~2.3.4", + "consolidation/robo": "^1.0.0", + "vlucas/phpdotenv": "^2.4" }, "autoload": { "psr-4": { "Magento\\": "tests/functional/Magento" - } + }, + "files": ["tests/_bootstrap.php"] }, "prefer-stable": true } diff --git a/dev/tests/acceptance/composer.lock b/dev/tests/acceptance/composer.lock index afe2640b442f1..f8c6bbc137211 100644 --- a/dev/tests/acceptance/composer.lock +++ b/dev/tests/acceptance/composer.lock @@ -4,111 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "9f292f6e226938ad82d1189da7aa4024", + "content-hash": "46ca2d50566f5069daef753664080c5a", "packages": [ - { - "name": "allure-framework/allure-codeception", - "version": "1.2.7", - "source": { - "type": "git", - "url": "https://github.com/allure-framework/allure-codeception.git", - "reference": "48598f4b4603b50b663bfe977260113a40912131" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/allure-framework/allure-codeception/zipball/48598f4b4603b50b663bfe977260113a40912131", - "reference": "48598f4b4603b50b663bfe977260113a40912131", - "shasum": "" - }, - "require": { - "allure-framework/allure-php-api": "~1.1.0", - "codeception/codeception": "~2.1", - "php": ">=5.4.0", - "symfony/filesystem": ">=2.6", - "symfony/finder": ">=2.6" - }, - "type": "library", - "autoload": { - "psr-0": { - "Yandex": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Ivan Krutov", - "email": "vania-pooh@yandex-team.ru", - "role": "Developer" - } - ], - "description": "A Codeception adapter for Allure report.", - "homepage": "http://allure.qatools.ru/", - "keywords": [ - "allure", - "attachments", - "cases", - "codeception", - "report", - "steps", - "testing" - ], - "time": "2018-03-07T11:18:27+00:00" - }, - { - "name": "allure-framework/allure-php-api", - "version": "1.1.4", - "source": { - "type": "git", - "url": "https://github.com/allure-framework/allure-php-adapter-api.git", - "reference": "a462a0da121681577033e13c123b6cc4e89cdc64" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/allure-framework/allure-php-adapter-api/zipball/a462a0da121681577033e13c123b6cc4e89cdc64", - "reference": "a462a0da121681577033e13c123b6cc4e89cdc64", - "shasum": "" - }, - "require": { - "jms/serializer": ">=0.16.0", - "moontoast/math": ">=1.1.0", - "php": ">=5.4.0", - "phpunit/phpunit": ">=4.0.0", - "ramsey/uuid": ">=3.0.0", - "symfony/http-foundation": ">=2.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Yandex": [ - "src/", - "test/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Ivan Krutov", - "email": "vania-pooh@yandex-team.ru", - "role": "Developer" - } - ], - "description": "PHP API for Allure adapter", - "homepage": "http://allure.qatools.ru/", - "keywords": [ - "allure", - "api", - "php", - "report" - ], - "time": "2016-12-07T12:15:46+00:00" - }, { "name": "behat/gherkin", "version": "v4.4.5", @@ -264,16 +161,16 @@ }, { "name": "codeception/stub", - "version": "1.0.2", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/Codeception/Stub.git", - "reference": "95fb7a36b81890dd2e5163e7ab31310df6f1bb99" + "reference": "681b62348837a5ef07d10d8a226f5bc358cc8805" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Stub/zipball/95fb7a36b81890dd2e5163e7ab31310df6f1bb99", - "reference": "95fb7a36b81890dd2e5163e7ab31310df6f1bb99", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/681b62348837a5ef07d10d8a226f5bc358cc8805", + "reference": "681b62348837a5ef07d10d8a226f5bc358cc8805", "shasum": "" }, "require": { @@ -293,7 +190,7 @@ "MIT" ], "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", - "time": "2018-02-18T13:56:56+00:00" + "time": "2018-05-17T09:31:08+00:00" }, { "name": "consolidation/annotated-command", @@ -674,141 +571,6 @@ ], "time": "2017-01-20T21:14:22+00:00" }, - { - "name": "doctrine/annotations", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "time": "2017-12-06T07:11:42+00:00" - }, - { - "name": "doctrine/collections", - "version": "v1.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", - "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "~0.1@dev", - "phpunit/phpunit": "^5.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Collections\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Collections Abstraction library", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "array", - "collections", - "iterator" - ], - "time": "2017-07-22T10:37:32+00:00" - }, { "name": "doctrine/instantiator", "version": "1.1.0", @@ -863,136 +625,41 @@ ], "time": "2017-07-22T11:58:36+00:00" }, - { - "name": "doctrine/lexer", - "version": "v1.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "lexer", - "parser" - ], - "time": "2014-09-09T13:34:57+00:00" - }, - { - "name": "epfremme/swagger-php", - "version": "v2.0.0", - "source": { - "type": "git", - "url": "https://github.com/epfremmer/swagger-php.git", - "reference": "eee28a442b7e6220391ec953d3c9b936354f23bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/epfremmer/swagger-php/zipball/eee28a442b7e6220391ec953d3c9b936354f23bc", - "reference": "eee28a442b7e6220391ec953d3c9b936354f23bc", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.2", - "doctrine/collections": "^1.3", - "jms/serializer": "^1.1", - "php": ">=5.5", - "phpoption/phpoption": "^1.1", - "symfony/yaml": "^2.7|^3.1" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "~4.8|~5.0", - "satooshi/php-coveralls": "^1.0" - }, - "type": "package", - "autoload": { - "psr-4": { - "Epfremme\\Swagger\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Edward Pfremmer", - "email": "epfremme@nerdery.com" - } - ], - "description": "Library for parsing swagger documentation into PHP entities for use in testing and code generation", - "time": "2016-09-26T17:24:17+00:00" - }, { "name": "facebook/webdriver", - "version": "1.5.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/facebook/php-webdriver.git", - "reference": "86b5ca2f67173c9d34340845dd690149c886a605" + "reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/86b5ca2f67173c9d34340845dd690149c886a605", - "reference": "86b5ca2f67173c9d34340845dd690149c886a605", + "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/bd8c740097eb9f2fc3735250fc1912bc811a954e", + "reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e", "shasum": "" }, "require": { "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", "ext-zip": "*", "php": "^5.6 || ~7.0", "symfony/process": "^2.8 || ^3.1 || ^4.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.0", - "guzzle/guzzle": "^3.4.1", - "php-coveralls/php-coveralls": "^1.0.2", + "jakub-onderka/php-parallel-lint": "^0.9.2", + "php-coveralls/php-coveralls": "^2.0", "php-mock/php-mock-phpunit": "^1.1", "phpunit/phpunit": "^5.7", "sebastian/environment": "^1.3.4 || ^2.0 || ^3.0", "squizlabs/php_codesniffer": "^2.6", "symfony/var-dumper": "^3.3 || ^4.0" }, + "suggest": { + "ext-SimpleXML": "For Firefox profile creation" + }, "type": "library", "extra": { "branch-alias": { @@ -1016,98 +683,7 @@ "selenium", "webdriver" ], - "time": "2017-11-15T11:08:09+00:00" - }, - { - "name": "flow/jsonpath", - "version": "0.4.0", - "source": { - "type": "git", - "url": "https://github.com/FlowCommunications/JSONPath.git", - "reference": "f0222818d5c938e4ab668ab2e2c079bd51a27112" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FlowCommunications/JSONPath/zipball/f0222818d5c938e4ab668ab2e2c079bd51a27112", - "reference": "f0222818d5c938e4ab668ab2e2c079bd51a27112", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "peekmo/jsonpath": "dev-master", - "phpunit/phpunit": "^4.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Flow\\JSONPath": "src/", - "Flow\\JSONPath\\Test": "tests/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Stephen Frank", - "email": "stephen@flowsa.com" - } - ], - "description": "JSONPath implementation for parsing, searching and flattening arrays", - "time": "2018-03-04T16:39:47+00:00" - }, - { - "name": "fzaninotto/faker", - "version": "v1.7.1", - "source": { - "type": "git", - "url": "https://github.com/fzaninotto/Faker.git", - "reference": "d3ed4cc37051c1ca52d22d76b437d14809fc7e0d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/d3ed4cc37051c1ca52d22d76b437d14809fc7e0d", - "reference": "d3ed4cc37051c1ca52d22d76b437d14809fc7e0d", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "ext-intl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", - "squizlabs/php_codesniffer": "^1.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "autoload": { - "psr-4": { - "Faker\\": "src/Faker/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "François Zaninotto" - } - ], - "description": "Faker is a PHP library that generates fake data for you.", - "keywords": [ - "data", - "faker", - "fixtures" - ], - "time": "2017-08-15T16:48:10+00:00" + "time": "2018-05-16T17:37:13+00:00" }, { "name": "grasmash/expander", @@ -1206,16 +782,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.3.2", + "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90" + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/68d0ea14d5a3f42a20e87632a5f84931e2709c90", - "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", "shasum": "" }, "require": { @@ -1225,7 +801,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", "psr/log": "^1.0" }, "suggest": { @@ -1267,7 +843,7 @@ "rest", "web service" ], - "time": "2018-03-26T16:33:04+00:00" + "time": "2018-04-22T15:46:56+00:00" }, { "name": "guzzlehttp/promises", @@ -1379,181 +955,11 @@ "message", "request", "response", - "stream", - "uri", - "url" - ], - "time": "2017-03-20T17:10:46+00:00" - }, - { - "name": "jms/metadata", - "version": "1.6.0", - "source": { - "type": "git", - "url": "https://github.com/schmittjoh/metadata.git", - "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/6a06970a10e0a532fb52d3959547123b84a3b3ab", - "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "doctrine/cache": "~1.0", - "symfony/cache": "~3.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5.x-dev" - } - }, - "autoload": { - "psr-0": { - "Metadata\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Class/method/property metadata management in PHP", - "keywords": [ - "annotations", - "metadata", - "xml", - "yaml" - ], - "time": "2016-12-05T10:18:33+00:00" - }, - { - "name": "jms/parser-lib", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/schmittjoh/parser-lib.git", - "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/parser-lib/zipball/c509473bc1b4866415627af0e1c6cc8ac97fa51d", - "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d", - "shasum": "" - }, - "require": { - "phpoption/phpoption": ">=0.9,<2.0-dev" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-0": { - "JMS\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache2" - ], - "description": "A library for easily creating recursive-descent parsers.", - "time": "2012-11-18T18:08:43+00:00" - }, - { - "name": "jms/serializer", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/schmittjoh/serializer.git", - "reference": "e7c53477ff55c21d1b1db7d062edc050a24f465f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/e7c53477ff55c21d1b1db7d062edc050a24f465f", - "reference": "e7c53477ff55c21d1b1db7d062edc050a24f465f", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "doctrine/instantiator": "^1.0.3", - "jms/metadata": "~1.1", - "jms/parser-lib": "1.*", - "php": "^5.5|^7.0", - "phpcollection/phpcollection": "~0.1", - "phpoption/phpoption": "^1.1" - }, - "conflict": { - "twig/twig": "<1.12" - }, - "require-dev": { - "doctrine/orm": "~2.1", - "doctrine/phpcr-odm": "^1.3|^2.0", - "ext-pdo_sqlite": "*", - "jackalope/jackalope-doctrine-dbal": "^1.1.5", - "phpunit/phpunit": "^4.8|^5.0", - "propel/propel1": "~1.7", - "psr/container": "^1.0", - "symfony/dependency-injection": "^2.7|^3.3|^4.0", - "symfony/expression-language": "^2.6|^3.0", - "symfony/filesystem": "^2.1", - "symfony/form": "~2.1|^3.0", - "symfony/translation": "^2.1|^3.0", - "symfony/validator": "^2.2|^3.0", - "symfony/yaml": "^2.1|^3.0", - "twig/twig": "~1.12|~2.0" - }, - "suggest": { - "doctrine/cache": "Required if you like to use cache functionality.", - "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.", - "symfony/yaml": "Required if you'd like to serialize data to YAML format." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.11-dev" - } - }, - "autoload": { - "psr-0": { - "JMS\\Serializer": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Asmir Mustafic", - "email": "goetas@gmail.com" - }, - { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.", - "homepage": "http://jmsyst.com/libs/serializer", - "keywords": [ - "deserialization", - "jaxb", - "json", - "serialization", - "xml" + "stream", + "uri", + "url" ], - "time": "2018-02-04T17:48:54+00:00" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "league/container", @@ -1620,194 +1026,30 @@ ], "time": "2017-05-10T09:20:27+00:00" }, - { - "name": "magento/magento2-functional-testing-framework", - "version": "2.2.0", - "source": { - "type": "git", - "url": "git@github.com:magento/magento2-functional-testing-framework.git", - "reference": "4dd196d745bf836cbf0c5904a1df6dd241124309" - }, - "require": { - "allure-framework/allure-codeception": "~1.2.6", - "codeception/codeception": "~2.3.4", - "consolidation/robo": "^1.0.0", - "epfremme/swagger-php": "^2.0", - "flow/jsonpath": ">0.2", - "fzaninotto/faker": "^1.6", - "mustache/mustache": "~2.5", - "php": "7.0.2|7.0.4|~7.0.6|~7.1.0|~7.2.0", - "symfony/process": "^2.8 || ^3.1 || ^4.0", - "vlucas/phpdotenv": "^2.4" - }, - "require-dev": { - "brainmaestro/composer-git-hooks": "^2.3", - "codacy/coverage": "^1.4", - "codeception/aspect-mock": "^2.0", - "goaop/framework": "2.1.2", - "php-coveralls/php-coveralls": "^1.0", - "phpmd/phpmd": "^2.6.0", - "rregeer/phpunit-coverage-check": "^0.1.4", - "sebastian/phpcpd": "~3.0", - "squizlabs/php_codesniffer": "1.5.3", - "symfony/stopwatch": "~3.4.6" - }, - "bin": [ - "bin/mftf" - ], - "type": "library", - "extra": { - "hooks": { - "pre-push": "bin/all-checks" - } - }, - "autoload": { - "psr-4": { - "Magento\\FunctionalTestingFramework\\": "src/Magento/FunctionalTestingFramework", - "MFTF\\": "dev/tests/functional/MFTF" - } - }, - "autoload-dev": { - "psr-4": { - "tests\\unit\\": "dev/tests/unit" - } - }, - "scripts": { - "tests": [ - "bin/phpunit-checks" - ], - "static": [ - "bin/static-checks" - ] - }, - "license": [ - "AGPL-3.0" - ], - "description": "Magento2 Functional Testing Framework", - "keywords": [ - "automation", - "functional", - "magento", - "testing" - ], - "time": "2018-04-24T01:46:09+00:00" - }, - { - "name": "moontoast/math", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/ramsey/moontoast-math.git", - "reference": "c2792a25df5cad4ff3d760dd37078fc5b6fccc79" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ramsey/moontoast-math/zipball/c2792a25df5cad4ff3d760dd37078fc5b6fccc79", - "reference": "c2792a25df5cad4ff3d760dd37078fc5b6fccc79", - "shasum": "" - }, - "require": { - "ext-bcmath": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "jakub-onderka/php-parallel-lint": "^0.9.0", - "phpunit/phpunit": "^4.7|>=5.0 <5.4", - "satooshi/php-coveralls": "^0.6.1", - "squizlabs/php_codesniffer": "^2.3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Moontoast\\Math\\": "src/Moontoast/Math/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" - } - ], - "description": "A mathematics library, providing functionality for large numbers", - "homepage": "https://github.com/ramsey/moontoast-math", - "keywords": [ - "bcmath", - "math" - ], - "time": "2017-02-16T16:54:46+00:00" - }, - { - "name": "mustache/mustache", - "version": "v2.12.0", - "source": { - "type": "git", - "url": "https://github.com/bobthecow/mustache.php.git", - "reference": "fe8fe72e9d580591854de404cc59a1b83ca4d19e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/fe8fe72e9d580591854de404cc59a1b83ca4d19e", - "reference": "fe8fe72e9d580591854de404cc59a1b83ca4d19e", - "shasum": "" - }, - "require": { - "php": ">=5.2.4" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "~1.11", - "phpunit/phpunit": "~3.7|~4.0|~5.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Mustache": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" - } - ], - "description": "A Mustache implementation in PHP.", - "homepage": "https://github.com/bobthecow/mustache.php", - "keywords": [ - "mustache", - "templating" - ], - "time": "2017-07-11T12:54:05+00:00" - }, { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "478465659fd987669df0bd8a9bf22a8710e5f1b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/478465659fd987669df0bd8a9bf22a8710e5f1b6", + "reference": "478465659fd987669df0bd8a9bf22a8710e5f1b6", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { @@ -1830,55 +1072,7 @@ "object", "object graph" ], - "time": "2017-10-19T19:58:43+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v2.0.12", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "autoload": { - "files": [ - "lib/random.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "pseudorandom", - "random" - ], - "time": "2018-04-04T21:24:14+00:00" + "time": "2018-05-29T17:25:09+00:00" }, { "name": "phar-io/manifest", @@ -1982,54 +1176,6 @@ "description": "Library for handling version information and constraints", "time": "2017-03-05T17:38:23+00:00" }, - { - "name": "phpcollection/phpcollection", - "version": "0.5.0", - "source": { - "type": "git", - "url": "https://github.com/schmittjoh/php-collection.git", - "reference": "f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6", - "reference": "f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6", - "shasum": "" - }, - "require": { - "phpoption/phpoption": "1.*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.4-dev" - } - }, - "autoload": { - "psr-0": { - "PhpCollection": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache2" - ], - "authors": [ - { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "General-Purpose Collection Library for PHP", - "keywords": [ - "collection", - "list", - "map", - "sequence", - "set" - ], - "time": "2015-05-17T12:39:23+00:00" - }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", @@ -2182,56 +1328,6 @@ ], "time": "2017-07-14T14:27:02+00:00" }, - { - "name": "phpoption/phpoption", - "version": "1.5.0", - "source": { - "type": "git", - "url": "https://github.com/schmittjoh/php-option.git", - "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/94e644f7d2051a5f0fcf77d81605f152eecff0ed", - "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "4.7.*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-0": { - "PhpOption\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache2" - ], - "authors": [ - { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Option Type for PHP", - "keywords": [ - "language", - "option", - "php", - "type" - ], - "time": "2015-07-25T16:39:46+00:00" - }, { "name": "phpspec/prophecy", "version": "1.7.6", @@ -2630,16 +1726,16 @@ }, { "name": "phpunit/phpunit-mock-objects", - "version": "5.0.6", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" + "reference": "3eaf040f20154d27d6da59ca2c6e28ac8fd56dce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3eaf040f20154d27d6da59ca2c6e28ac8fd56dce", + "reference": "3eaf040f20154d27d6da59ca2c6e28ac8fd56dce", "shasum": "" }, "require": { @@ -2685,7 +1781,7 @@ "mock", "xunit" ], - "time": "2018-01-06T05:45:45+00:00" + "time": "2018-05-29T13:50:43+00:00" }, { "name": "psr/container", @@ -2833,86 +1929,6 @@ ], "time": "2016-10-10T12:19:37+00:00" }, - { - "name": "ramsey/uuid", - "version": "3.7.3", - "source": { - "type": "git", - "url": "https://github.com/ramsey/uuid.git", - "reference": "44abcdad877d9a46685a3a4d221e3b2c4b87cb76" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/44abcdad877d9a46685a3a4d221e3b2c4b87cb76", - "reference": "44abcdad877d9a46685a3a4d221e3b2c4b87cb76", - "shasum": "" - }, - "require": { - "paragonie/random_compat": "^1.0|^2.0", - "php": "^5.4 || ^7.0" - }, - "replace": { - "rhumsaa/uuid": "self.version" - }, - "require-dev": { - "codeception/aspect-mock": "^1.0 | ~2.0.0", - "doctrine/annotations": "~1.2.0", - "goaop/framework": "1.0.0-alpha.2 | ^1.0 | ^2.1", - "ircmaxell/random-lib": "^1.1", - "jakub-onderka/php-parallel-lint": "^0.9.0", - "mockery/mockery": "^0.9.9", - "moontoast/math": "^1.1", - "php-mock/php-mock-phpunit": "^0.3|^1.1", - "phpunit/phpunit": "^4.7|^5.0", - "squizlabs/php_codesniffer": "^2.3" - }, - "suggest": { - "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", - "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", - "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", - "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", - "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", - "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Ramsey\\Uuid\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marijn Huizendveld", - "email": "marijn.huizendveld@gmail.com" - }, - { - "name": "Thibaud Fabre", - "email": "thibaud@aztech.io" - }, - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" - } - ], - "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", - "homepage": "https://github.com/ramsey/uuid", - "keywords": [ - "guid", - "identifier", - "uuid" - ], - "time": "2018-01-20T00:28:24+00:00" - }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.1", @@ -3474,16 +2490,16 @@ }, { "name": "symfony/browser-kit", - "version": "v4.0.8", + "version": "v4.1.0", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "c43bfa0182363b3fd64331b5e64e467349ff4670" + "reference": "16355a5d0f1499c77efee5ff68d8ea61624d4da1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/c43bfa0182363b3fd64331b5e64e467349ff4670", - "reference": "c43bfa0182363b3fd64331b5e64e467349ff4670", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/16355a5d0f1499c77efee5ff68d8ea61624d4da1", + "reference": "16355a5d0f1499c77efee5ff68d8ea61624d4da1", "shasum": "" }, "require": { @@ -3500,7 +2516,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3527,20 +2543,20 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2018-03-19T22:35:49+00:00" + "time": "2018-04-06T10:52:03+00:00" }, { "name": "symfony/console", - "version": "v4.0.8", + "version": "v4.0.9", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "aad9a6fe47319f22748fd764f52d3a7ca6fa6b64" + "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/aad9a6fe47319f22748fd764f52d3a7ca6fa6b64", - "reference": "aad9a6fe47319f22748fd764f52d3a7ca6fa6b64", + "url": "https://api.github.com/repos/symfony/console/zipball/3e820bc2c520a87ca209ad8fa961c97f42e0b4ae", + "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae", "shasum": "" }, "require": { @@ -3560,7 +2576,7 @@ "symfony/process": "~3.4|~4.0" }, "suggest": { - "psr/log": "For using the console logger", + "psr/log-implementation": "For using the console logger", "symfony/event-dispatcher": "", "symfony/lock": "", "symfony/process": "" @@ -3595,20 +2611,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-04-03T05:24:00+00:00" + "time": "2018-04-30T01:23:47+00:00" }, { "name": "symfony/css-selector", - "version": "v4.0.8", + "version": "v4.1.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "03f965583147957f1ecbad7ea1c9d6fd5e525ec2" + "reference": "03ac71606ecb0b0ce792faa17d74cc32c2949ef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/03f965583147957f1ecbad7ea1c9d6fd5e525ec2", - "reference": "03f965583147957f1ecbad7ea1c9d6fd5e525ec2", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/03ac71606ecb0b0ce792faa17d74cc32c2949ef4", + "reference": "03ac71606ecb0b0ce792faa17d74cc32c2949ef4", "shasum": "" }, "require": { @@ -3617,7 +2633,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3648,24 +2664,25 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2018-03-19T22:35:49+00:00" + "time": "2018-05-30T07:26:09+00:00" }, { "name": "symfony/dom-crawler", - "version": "v4.0.8", + "version": "v4.1.0", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "d6c04c7532535b5e0b63db45b543cd60818e0fbc" + "reference": "3350cacf151b48d903114ab8f7a4ccb23e07e10a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/d6c04c7532535b5e0b63db45b543cd60818e0fbc", - "reference": "d6c04c7532535b5e0b63db45b543cd60818e0fbc", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/3350cacf151b48d903114ab8f7a4ccb23e07e10a", + "reference": "3350cacf151b48d903114ab8f7a4ccb23e07e10a", "shasum": "" }, "require": { "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { @@ -3677,7 +2694,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3704,11 +2721,11 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2018-03-19T22:35:49+00:00" + "time": "2018-05-01T23:02:13+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.0.8", + "version": "v4.0.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -3771,7 +2788,7 @@ }, { "name": "symfony/filesystem", - "version": "v4.0.8", + "version": "v4.0.9", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -3820,7 +2837,7 @@ }, { "name": "symfony/finder", - "version": "v4.0.8", + "version": "v4.0.9", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -3868,38 +2885,34 @@ "time": "2018-04-04T05:10:37+00:00" }, { - "name": "symfony/http-foundation", - "version": "v4.0.8", + "name": "symfony/polyfill-ctype", + "version": "v1.8.0", "source": { "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "d0864a82e5891ab61d31eecbaa48bed5a09b8e6c" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d0864a82e5891ab61d31eecbaa48bed5a09b8e6c", - "reference": "d0864a82e5891ab61d31eecbaa48bed5a09b8e6c", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/polyfill-mbstring": "~1.1" - }, - "require-dev": { - "symfony/expression-language": "~3.4|~4.0" + "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "1.8-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" + "Symfony\\Polyfill\\Ctype\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3907,31 +2920,37 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" } ], - "description": "Symfony HttpFoundation Component", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", - "time": "2018-04-03T05:24:00+00:00" + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-04-30T19:57:29+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + "reference": "3296adf6a6454a050679cde90f95350ad604b171" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", "shasum": "" }, "require": { @@ -3943,7 +2962,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -3977,11 +2996,11 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2018-04-26T10:06:28+00:00" }, { "name": "symfony/process", - "version": "v4.0.8", + "version": "v4.0.9", "source": { "type": "git", "url": "https://github.com/symfony/process.git", @@ -4030,20 +3049,20 @@ }, { "name": "symfony/yaml", - "version": "v3.4.8", + "version": "v4.0.9", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0" + "reference": "275ad099e4cbe612a2acbca14a16dd1c5311324d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a42f9da85c7c38d59f5e53f076fe81a091f894d0", - "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0", + "url": "https://api.github.com/repos/symfony/yaml/zipball/275ad099e4cbe612a2acbca14a16dd1c5311324d", + "reference": "275ad099e4cbe612a2acbca14a16dd1c5311324d", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3" }, "conflict": { "symfony/console": "<3.4" @@ -4057,7 +3076,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -4084,7 +3103,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-04-03T05:14:20+00:00" + "time": "2018-04-08T08:49:08+00:00" }, { "name": "theseer/tokenizer", @@ -4233,6 +3252,8 @@ "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, - "platform": [], + "platform": { + "php": "~7.1.3||~7.2.0" + }, "platform-dev": [] } diff --git a/dev/tests/acceptance/pre-install.php b/dev/tests/acceptance/pre-install.php deleted file mode 100644 index 4021dc1094948..0000000000000 --- a/dev/tests/acceptance/pre-install.php +++ /dev/null @@ -1,395 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/** - * @codingStandardsIgnoreStart - * @SuppressWarnings(PHPMD) - */ -class CliColors { - private $foreground_colors = array(); - private $background_colors = array(); - - public function __construct() { - // Set up shell colors - $this->foreground_colors['black'] = '0;30'; - $this->foreground_colors['dark_gray'] = '1;30'; - $this->foreground_colors['blue'] = '0;34'; - $this->foreground_colors['light_blue'] = '1;34'; - $this->foreground_colors['green'] = '0;32'; - $this->foreground_colors['light_green'] = '1;32'; - $this->foreground_colors['cyan'] = '0;36'; - $this->foreground_colors['light_cyan'] = '1;36'; - $this->foreground_colors['red'] = '0;31'; - $this->foreground_colors['light_red'] = '1;31'; - $this->foreground_colors['purple'] = '0;35'; - $this->foreground_colors['light_purple'] = '1;35'; - $this->foreground_colors['brown'] = '0;33'; - $this->foreground_colors['yellow'] = '1;33'; - $this->foreground_colors['light_gray'] = '0;37'; - $this->foreground_colors['white'] = '1;37'; - - $this->background_colors['black'] = '40'; - $this->background_colors['red'] = '41'; - $this->background_colors['green'] = '42'; - $this->background_colors['yellow'] = '43'; - $this->background_colors['blue'] = '44'; - $this->background_colors['magenta'] = '45'; - $this->background_colors['cyan'] = '46'; - $this->background_colors['light_gray'] = '47'; - } - - /** - * Returns colored string - * - * @param $string - * @param null $foreground_color - * @param null $background_color - * @return string - */ - public function getColoredString($string, $foreground_color = null, $background_color = null) { - $colored_string = ""; - - // Check if given foreground color found - if (isset($this->foreground_colors[$foreground_color])) { - $colored_string .= "\033[" . $this->foreground_colors[$foreground_color] . "m"; - } - // Check if given background color found - if (isset($this->background_colors[$background_color])) { - $colored_string .= "\033[" . $this->background_colors[$background_color] . "m"; - } - - // Add string and end coloring - $colored_string .= $string . "\033[0m"; - - return $colored_string; - } - - /** - * Returns all foreground color names - * - * @return array - */ - public function getForegroundColors() { - return array_keys($this->foreground_colors); - } - - /** - * Returns all background color names - * - * @return array - */ - public function getBackgroundColors() { - return array_keys($this->background_colors); - } -} - -/** - * @SuppressWarnings(PHPMD) - */ -class PreInstallCheck { - private $installedViaBrew = false; - private $filePath = ''; - private $seleniumJarVersion = ''; - - private $phpWebsite = 'http://php.net/manual/en/install.php'; - private $composerWebsite = 'https://getcomposer.org/download/'; - private $javaWebsite = 'https://www.java.com/en/download/'; - private $allureCliWebsite = 'https://docs.qameta.io/allure/latest/#_installing_a_commandline'; - private $seleniumWebsite = 'http://www.seleniumhq.org/download/'; - private $chromeDriverWebsite = 'https://sites.google.com/a/chromium.org/chromedriver/downloads'; - private $geckoDriverWebsite = 'https://github.com/mozilla/geckodriver'; - private $phantomJsWebsite = 'http://phantomjs.org/'; - - private $phpSupportedVersion = '7.1.0'; - private $composerSupportedVersion = '1.3.0'; - private $javaSupportedVersion = '1.8.0'; - private $allureCliSupportedVersion = '2.3.0'; - private $seleniumSupportedVersion = '3.6.0'; - private $chromeDriverSupportedVersion = '2.33.0'; - private $geckoDriverSupportedVersion = '0.19.0'; - private $phantomJsSupportedVersion = '2.1.0'; - - private $getPhpVersion; - private $getComposerVersion; - private $getJavaVersion; - private $getAllureCliVersion; - private $getSeleniumVersion; - private $getChromeDriverVersion; - private $getGeckoDriverVersion; - private $getPhantomJsVersion; - - private $phpVersion; - private $composerVersion; - private $javaVersion; - private $allureCliVersion; - private $seleniumVersion; - private $chromeDriverVersion; - private $geckoDriverVersion; - private $phantomJsVersion; - - private $phpStatus; - private $composerStatus; - private $javaStatus; - private $allureCliStatus; - private $seleniumStatus; - private $chromeDriverStatus; - private $geckoDriverStatus; - private $phantomJsStatus; - - function __construct() { - $this->didYouInstallViaBrew(); - - $this->getPhpVersion = shell_exec('php --version'); - $this->getComposerVersion = shell_exec('composer --version'); - $this->getJavaVersion = shell_exec("java -version 2>&1"); - $this->getAllureCliVersion = shell_exec('allure --version'); - $this->getSeleniumVersion = $this->getSeleniumVersion(); - $this->getChromeDriverVersion = $this->getChromeDriverVersion(); - $this->getGeckoDriverVersion = shell_exec('geckodriver --version'); - $this->getPhantomJsVersion = $this->getPhantomJsVersion(); - - $this->phpVersion = $this->parseVersion($this->getPhpVersion); - $this->composerVersion = $this->parseVersion($this->getComposerVersion); - $this->javaVersion = $this->parseJavaVersion($this->getJavaVersion); - $this->allureCliVersion = $this->parseVersion($this->getAllureCliVersion); - $this->seleniumVersion = $this->parseVersion($this->getSeleniumVersion); - $this->chromeDriverVersion = $this->parseVersion($this->getChromeDriverVersion); - $this->geckoDriverVersion = $this->parseVersion($this->getGeckoDriverVersion); - $this->phantomJsVersion = $this->parseVersion($this->getPhantomJsVersion); - - // String of null Versions - For Testing -// $this->phpVersion = null; -// $this->composerVersion = null; -// $this->javaVersion = null; -// $this->allureCliVersion = null; -// $this->seleniumVersion = null; -// $this->chromeDriverVersion = null; -// $this->geckoDriverVersion = null; -// $this->phantomJsVersion = null; - - // String of invalid Versions - For Testing -// $this->phpVersion = '7.0.0'; -// $this->composerVersion = '1.0.0'; -// $this->javaVersion = '1.0.0'; -// $this->allureCliVersion = '2.0.0'; -// $this->seleniumVersion = '3.0.0'; -// $this->chromeDriverVersion = '2.0.0'; -// $this->geckoDriverVersion = '0.0.0'; -// $this->phantomJsVersion = '2.0.0'; - - $this->phpStatus = $this->verifyVersion('PHP', $this->phpVersion, $this->phpSupportedVersion, $this->phpWebsite); - $this->composerStatus = $this->verifyVersion('Composer', $this->composerVersion, $this->composerSupportedVersion, $this->composerWebsite); - $this->javaStatus = $this->verifyVersion('Java', $this->javaVersion, $this->javaSupportedVersion, $this->javaWebsite); - $this->allureCliStatus = $this->verifyVersion('Allure CLI', $this->allureCliVersion, $this->allureCliSupportedVersion, $this->allureCliWebsite); - $this->seleniumStatus = $this->verifyVersion('Selenium Standalone Server', $this->seleniumVersion, $this->seleniumSupportedVersion, $this->seleniumWebsite); - $this->chromeDriverStatus = $this->verifyVersion('ChromeDriver', $this->chromeDriverVersion, $this->chromeDriverSupportedVersion, $this->chromeDriverWebsite); - $this->geckoDriverStatus = $this->verifyVersion('GeckoDriver', $this->geckoDriverVersion, $this->geckoDriverSupportedVersion, $this->geckoDriverWebsite); - $this->phantomJsStatus = $this->verifyVersion('PhantomJS', $this->phantomJsVersion, $this->phantomJsSupportedVersion, $this->phantomJsWebsite); - - ECHO "\n"; - $mask = "|%-13.13s |%18.18s |%18.18s |%-23.23s |\n"; - printf("---------------------------------------------------------------------------------\n"); - printf($mask, ' Software', 'Supported Version', 'Installed Version', ' Status'); - printf("---------------------------------------------------------------------------------\n"); - printf($mask, ' PHP', $this->phpSupportedVersion . '+', $this->phpVersion, ' ' . $this->phpStatus); - printf($mask, ' Composer', $this->composerSupportedVersion . '+', $this->composerVersion, ' ' . $this->composerStatus); - printf($mask, ' Java', $this->javaSupportedVersion . '+', $this->javaVersion, ' ' . $this->javaStatus); - printf($mask, ' Allure CLI', $this->allureCliSupportedVersion . '+', $this->allureCliVersion, ' ' . $this->allureCliStatus); - printf($mask, ' Selenium', $this->seleniumSupportedVersion . '+', $this->seleniumVersion, ' ' . $this->seleniumStatus); - printf($mask, ' ChromeDriver', $this->chromeDriverSupportedVersion . '+', $this->chromeDriverVersion, ' ' . $this->chromeDriverStatus); - printf($mask, ' GeckoDriver', $this->geckoDriverSupportedVersion . '+', $this->geckoDriverVersion, ' ' . $this->geckoDriverStatus); - printf($mask, ' PhantomJS', $this->phantomJsSupportedVersion . '+', $this->phantomJsVersion, ' ' . $this->phantomJsStatus); - printf("---------------------------------------------------------------------------------\n"); - } - - /** - * Ask if they installed the Browser Drivers via Brew. - * Brew installs things globally making them easier for us to access. - */ - public function didYouInstallViaBrew() - { - ECHO "Did you install Selenium Server, ChromeDriver, GeckoDriver and PhantomJS using Brew? (y/n) "; - $handle1 = fopen ("php://stdin","r"); - $line1 = fgets($handle1); - if (trim($line1) != 'y') { - ECHO "Where did you save the files? (ex /Users/first_last/Automation/) "; - $handle2 = fopen ("php://stdin","r"); - $this->filePath = fgets($handle2); - fclose($handle2); - - ECHO "Which selenium-server-standalone-X.X.X.jar file did you download? (ex 3.6.0) "; - $handle3 = fopen ("php://stdin","r"); - $this->seleniumJarVersion = fgets($handle3); - fclose($handle3); - fclose($handle1); - ECHO "\n"; - } else { - $this->installedViaBrew = true; - fclose($handle1); - ECHO "\n"; - } - } - - /** - * Parse the string that is returned for the Version number only. - * - * @param $stdout - * @return null - */ - public function parseVersion($stdout) - { - preg_match("/\d+(?:\.\d+)+/", $stdout, $matches); - - if (!is_null($matches) && isset($matches[0])) { - return $matches[0]; - } else { - return null; - } - } - - /** - * Parse the string that is returned for the Version number only. - * The message Java returns differs from the others hence the separate function. - * - * @param $stdout - * @return null - */ - public function parseJavaVersion($stdout) - { - preg_match('/\"(.+?)\"/', $stdout, $output_array); - - if (!is_null($output_array)) { - return $output_array[1]; - } else { - return null; - } - } - - /** - * Get the Selenium Server version based on how it was installed. - * - * @return string - */ - public function getSeleniumVersion() - { - $this->installedViaBrew; - $this->filePath; - $this->seleniumJarVersion; - - if ($this->installedViaBrew) { - return shell_exec('selenium-server --version'); - } else { - $command = sprintf('java -jar %s/selenium-server-standalone-%s.jar --version', $this->filePath, $this->seleniumJarVersion); - $command = str_replace(array("\r", "\n"), '', $command) . "\n"; - return shell_exec($command); - } - } - - /** - * Get the ChromeDriver version based on how it was installed. - * - * @return string - */ - public function getChromeDriverVersion() - { - $this->installedViaBrew; - $this->filePath; - - if ($this->installedViaBrew) { - return shell_exec('chromedriver --version'); - } else { - $command = sprintf('%s/chromedriver --version', $this->filePath); - $command = str_replace(array("\r", "\n"), '', $command) . "\n"; - return shell_exec($command); - } - } - - /** - * Get the PhantomJS version based on how it was installed. - * - * @return string - */ - public function getPhantomJsVersion() - { - $this->installedViaBrew; - $this->filePath; - - if ($this->installedViaBrew) { - return shell_exec('phantomjs --version'); - } else { - $command = sprintf('%s/phantomjs --version', $this->filePath); - $command = str_replace(array("\r", "\n"), '', $command) . "\n"; - return shell_exec($command); - } - } - - /** - * Print a "Valid Version Detected" message in color. - * - * @param $softwareName - */ - public function printValidVersion($softwareName) - { - $colors = new CliColors(); - $string = sprintf("%s detected. Version is supported!", $softwareName); - ECHO $colors->getColoredString($string, "black", "green") . "\n"; - } - - /** - * Print a "Upgraded Version Needed" message in color. - * - * @param $softwareName - * @param $supportedVersion - * @param $website - */ - public function printUpgradeVersion($softwareName, $supportedVersion, $website) - { - $colors = new CliColors(); - $string = sprintf("Unsupported version of %s detected. Please upgrade to v%s+: %s", $softwareName, $supportedVersion, $website); - ECHO $colors->getColoredString($string, "black", "yellow") . "\n"; - } - - /** - * Print a "Not Installed. Install Required." message in color. - * - * @param $softwareName - * @param $supportedVersion - * @param $website - */ - public function printNoInstalledVersion($softwareName, $supportedVersion, $website) - { - $colors = new CliColors(); - $string = sprintf("%s not detected. Please install v%s+: %s", $softwareName, $supportedVersion, $website); - ECHO $colors->getColoredString($string, "black", "red") . "\n"; - } - - /** - * Verify that the versions. - * Print the correct status message. - * - * @param $softwareName - * @param $installedVersion - * @param $supportedVersion - * @param $website - * @return string - */ - public function verifyVersion($softwareName, $installedVersion, $supportedVersion, $website) - { - if (is_null($installedVersion)) { - $this->printNoInstalledVersion($softwareName, $supportedVersion, $website); - return 'Installation Required!'; - } else if ($installedVersion >= $supportedVersion) { - $this->printValidVersion($softwareName); - return 'Correct Version!'; - } else { - $this->printUpgradeVersion($softwareName, $supportedVersion, $website); - return 'Upgrade Required!'; - } - } -} - -$preCheck = new PreInstallCheck(); -// @codingStandardsIgnoreEnd \ No newline at end of file diff --git a/dev/tests/acceptance/tests/_bootstrap.php b/dev/tests/acceptance/tests/_bootstrap.php index d15481d18098c..ee39fc1a09da6 100644 --- a/dev/tests/acceptance/tests/_bootstrap.php +++ b/dev/tests/acceptance/tests/_bootstrap.php @@ -1,110 +1,5 @@ <?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -$bootstrapRoot = dirname(__DIR__); -$projectRootPath = $bootstrapRoot; - -// If we're under a vendor directory, find project root. -if (strpos($bootstrapRoot, '/vendor') !== false) { - $projectRootPath = substr($bootstrapRoot, 0, strpos($bootstrapRoot, '/vendor/')); -} - -define('PROJECT_ROOT', $projectRootPath); - - -//Load base paths from composer autoload file -$autoloadFile = PROJECT_ROOT . '/vendor/autoload.php'; - -$loader = require $autoloadFile; - -// Package Names. -$FW_PACKAGE_NAME = "Magento\FunctionalTestingFramework\\"; -$TESTS_PACKAGE_NAME = "TODO"; -$MAGENTO_PACKAGE_NAME = "Magento\\"; - -// Find framework path -$COMPOSER_FW_FULL_PREFIX = $loader->getPrefixesPsr4()[$FW_PACKAGE_NAME][0] ?? null; -if ($COMPOSER_FW_FULL_PREFIX === null) { - throw new Exception( - "You must have the magento/magento2-functional-testing-framework - installed to be able to generate tests." - ); -} -$FW_PATH = substr( - $COMPOSER_FW_FULL_PREFIX, - 0, - strpos($COMPOSER_FW_FULL_PREFIX, "/src/Magento/FunctionalTestingFramework") -); - -// Find tests path -$COMPOSER_TEST_FULL_PREFIX = $loader->getPrefixesPsr4()[$TESTS_PACKAGE_NAME][0] ?? null; -if ($COMPOSER_TEST_FULL_PREFIX === null) { - $TEST_PATH = __DIR__ . "/functional"; -} else { - // Can't determine what to trim; we don't know the package name/structure yet - $TEST_PATH = $COMPOSER_TEST_FULL_PREFIX; -} - -// We register "Magento\\" to "tests/functional/Magento" for our own class loading, need to try and find a -// prefix that isn't that one. -$COMPOSER_MAGENTO_PREFIXES = $loader->getPrefixesPsr4()[$MAGENTO_PACKAGE_NAME]; -$COMPOSER_MAGENTO_FULL_PREFIX = null; -foreach ($COMPOSER_MAGENTO_PREFIXES as $path) { - if (strpos($path, "tests/functional/Magento") === 0) { - $COMPOSER_MAGENTO_FULL_PREFIX = $path; - } -} -if ($COMPOSER_MAGENTO_FULL_PREFIX === null) { - $MAGENTO_PATH = dirname(__DIR__ . "/../../../../../"); -} else { - $MAGENTO_PATH = substr( - $COMPOSER_MAGENTO_FULL_PREFIX, - 0, - strpos($COMPOSER_MAGENTO_FULL_PREFIX, "/app/code/Magento") - ); -} - -$RELATIVE_TESTS_MODULE_PATH = '/Magento/FunctionalTest'; - -defined('MAGENTO_BP') || define('MAGENTO_BP', realpath($MAGENTO_PATH)); - -//Load constants from .env file -if (file_exists(MAGENTO_BP . '/dev/tests/acceptance/.env')) { - $env = new \Dotenv\Loader(MAGENTO_BP . '/dev/tests/acceptance/.env'); - $env->load(); - - if (array_key_exists('TESTS_MODULE_PATH', $_ENV) xor array_key_exists('TESTS_BP', $_ENV)) { - throw new Exception( - 'You must define both parameters TESTS_BP and TESTS_MODULE_PATH or neither parameter' - ); - } - - foreach ($_ENV as $key => $var) { - defined($key) || define($key, $var); - } - - defined('MAGENTO_CLI_COMMAND_PATH') || define( - 'MAGENTO_CLI_COMMAND_PATH', - 'dev/tests/acceptance/utils/command.php' - ); - $env->setEnvironmentVariable('MAGENTO_CLI_COMMAND_PATH', MAGENTO_CLI_COMMAND_PATH); - - defined('MAGENTO_CLI_COMMAND_PARAMETER') || define('MAGENTO_CLI_COMMAND_PARAMETER', 'command'); - $env->setEnvironmentVariable('MAGENTO_CLI_COMMAND_PARAMETER', MAGENTO_CLI_COMMAND_PARAMETER); -} - -defined('FW_BP') || define('FW_BP', realpath($FW_PATH)); -defined('TESTS_BP') || define('TESTS_BP', realpath($TEST_PATH)); -defined('TESTS_MODULE_PATH') || define( - 'TESTS_MODULE_PATH', - realpath($TEST_PATH . $RELATIVE_TESTS_MODULE_PATH) -); - -// add the debug flag here -$debug_mode = $_ENV['MFTF_DEBUG'] ?? false; -if (!(bool)$debug_mode && extension_loaded('xdebug')) { - xdebug_disable(); -} +//TODO remove this file once MFTF is fully decoupled from Magento +// Need to load in the root level autload file +require_once realpath(dirname(__DIR__) . "/../../../vendor/autoload.php"); diff --git a/dev/tests/acceptance/tests/functional.suite.dist.yml b/dev/tests/acceptance/tests/functional.suite.dist.yml deleted file mode 100644 index e01c46ea7c649..0000000000000 --- a/dev/tests/acceptance/tests/functional.suite.dist.yml +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright © Magento, Inc. All rights reserved. -# See COPYING.txt for license details. - -# Codeception Test Suite Configuration -# -# Suite for acceptance tests. -# Perform tests in browser using the WebDriver or PhpBrowser. -# If you need both WebDriver and PHPBrowser tests - create a separate suite. - -class_name: AcceptanceTester -namespace: Magento\FunctionalTestingFramework -modules: - enabled: - - \Magento\FunctionalTestingFramework\Module\MagentoWebDriver - - \Magento\FunctionalTestingFramework\Helper\Acceptance - - \Magento\FunctionalTestingFramework\Helper\MagentoFakerData - - \Magento\FunctionalTestingFramework\Module\MagentoRestDriver: - url: "%MAGENTO_BASE_URL%/rest/default/V1/" - username: "%MAGENTO_ADMIN_USERNAME%" - password: "%MAGENTO_ADMIN_PASSWORD%" - depends: PhpBrowser - part: Json - - \Magento\FunctionalTestingFramework\Module\MagentoSequence - - \Magento\FunctionalTestingFramework\Module\MagentoAssert - - Asserts - config: - \Magento\FunctionalTestingFramework\Module\MagentoWebDriver: - url: "%MAGENTO_BASE_URL%" - backend_name: "%MAGENTO_BACKEND_NAME%" - browser: 'chrome' - window_size: maximize - username: "%MAGENTO_ADMIN_USERNAME%" - password: "%MAGENTO_ADMIN_PASSWORD%" - pageload_timeout: 30 - host: %SELENIUM_HOST% - port: %SELENIUM_PORT% - protocol: %SELENIUM_PROTOCOL% - path: %SELENIUM_PATH% - capabilities: - chromeOptions: - args: ["--start-maximized", "--disable-extensions", "--enable-automation"] - diff --git a/dev/tests/acceptance/tests/functional/_bootstrap.php b/dev/tests/acceptance/tests/functional/_bootstrap.php deleted file mode 100644 index ac7a13ea41d29..0000000000000 --- a/dev/tests/acceptance/tests/functional/_bootstrap.php +++ /dev/null @@ -1,8 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -// Here you can initialize variables that will be available to your tests -require_once dirname(__DIR__) . '/_bootstrap.php'; From a7138bc1b562ef7cbc156aa57f51a1c182cf3196 Mon Sep 17 00:00:00 2001 From: Alex Paliarush <apaliarush@magento.com> Date: Wed, 30 May 2018 13:51:22 -0500 Subject: [PATCH 0870/2023] ENGCOM-1663: Include 'products' in category query #48 --- .../Magento/GraphQl/Catalog/CategoryTest.php | 14 +------------ .../Catalog/_files/categories_indexed.php | 21 +++++++++++++++++++ .../_files/categories_indexed_rollback.php | 21 +++++++++++++++++++ 3 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php index 8fc19a21421c0..d82b15e3990e9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php @@ -115,23 +115,11 @@ public function testCategoriesTree() /** * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/categories.php + * @magentoApiDataFixture Magento/Catalog/_files/categories_indexed.php * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testCategoryProducts() { - /** @var \Magento\Catalog\Model\Indexer\Category\Product\Processor $categoryProductIndexer */ - $categoryProductIndexer = $this->objectManager->get( - \Magento\Catalog\Model\Indexer\Category\Product\Processor::class - ); - $categoryProductIndexer->reindexAll(); - - /** @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor $inventoryIndexer */ - $inventoryIndexer = $this->objectManager->get( - \Magento\CatalogInventory\Model\Indexer\Stock\Processor::class - ); - $inventoryIndexer->reindexAll(); - $categoryId = 4; $query = <<<QUERY { diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php new file mode 100644 index 0000000000000..f76370978404d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +include __DIR__ . '/categories.php'; + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +/** @var \Magento\Catalog\Model\Indexer\Category\Product\Processor $categoryProductIndexer */ +$categoryProductIndexer = $objectManager->get( + \Magento\Catalog\Model\Indexer\Category\Product\Processor::class +); +$categoryProductIndexer->reindexAll(); + +/** @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor $inventoryIndexer */ +$inventoryIndexer = $objectManager->get( + \Magento\CatalogInventory\Model\Indexer\Stock\Processor::class +); +$inventoryIndexer->reindexAll(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php new file mode 100644 index 0000000000000..573fb7c3a2b11 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +include __DIR__ . '/categories_rollback.php'; + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +/** @var \Magento\Catalog\Model\Indexer\Category\Product\Processor $categoryProductIndexer */ +$categoryProductIndexer = $objectManager->get( + \Magento\Catalog\Model\Indexer\Category\Product\Processor::class +); +$categoryProductIndexer->reindexAll(); + +/** @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor $inventoryIndexer */ +$inventoryIndexer = $objectManager->get( + \Magento\CatalogInventory\Model\Indexer\Stock\Processor::class +); +$inventoryIndexer->reindexAll(); From c6134b0fa2a8fd6e6ea1f1a8ac7a550cece28cad Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@magento.com> Date: Wed, 30 May 2018 15:05:09 -0500 Subject: [PATCH 0871/2023] MC-138: Guest customer should be able to advance search configurable product with product name MC-144: Guest customer should be able to advance search configurable product with product sku MC-237: Guest customer should be able to advance search configurable product with product description MC-240: Guest customer should be able to advance search configurable product with product short description - added mftf tests --- .../AdvanceCatalogSearchSimpleProductTest.xml | 22 ++ ...AdvanceCatalogSearchVirtualProductTest.xml | 51 ++++ .../AdvanceCatalogSearchConfigurableTest.xml | 64 +++++ ...AdvanceCatalogSearchSimpleProductTest.xml} | 63 +---- ...AdvanceCatalogSearchVirtualProductTest.xml | 80 ++++++ ...dvanceCatalogSearchVirtualProductsTest.xml | 141 --------- .../Data/ConfigurableProductData.xml | 13 + .../AdvanceCatalogSearchConfigurableTest.xml | 267 ++++++++++++++++++ 8 files changed, 502 insertions(+), 199 deletions(-) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdvanceCatalogSearchSimpleProductTest.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdvanceCatalogSearchVirtualProductTest.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchConfigurableTest.xml rename dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/{AdvanceCatalogSearchSimpleProductsTest.xml => AdvanceCatalogSearchSimpleProductTest.xml} (60%) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchVirtualProductTest.xml delete mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchVirtualProductsTest.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/AdvanceCatalogSearchConfigurableTest.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdvanceCatalogSearchSimpleProductTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdvanceCatalogSearchSimpleProductTest.xml new file mode 100644 index 0000000000000..aed0de5800153 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdvanceCatalogSearchSimpleProductTest.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiProductWithDescription" stepKey="createProductOne"/> + </before> + <after> + <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> + </after> + </test> +</tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdvanceCatalogSearchVirtualProductTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdvanceCatalogSearchVirtualProductTest.xml new file mode 100644 index 0000000000000..775754143bc7e --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdvanceCatalogSearchVirtualProductTest.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdvanceCatalogSearchVirtualProductByNameTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> + </before> + </test> + <test name="AdvanceCatalogSearchVirtualProductBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> + </before> + </test> + <test name="AdvanceCatalogSearchVirtualProductByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> + </before> + </test> + <test name="AdvanceCatalogSearchVirtualProductByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> + </before> + </test> + <test name="AdvanceCatalogSearchVirtualProductByPriceTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> + </before> + </test> +</tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchConfigurableTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchConfigurableTest.xml new file mode 100644 index 0000000000000..88b3ed0f9419d --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchConfigurableTest.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdvanceCatalogSearchConfigurableByNameTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search configurable product with product name"/> + <description value="Guest customer should be able to advance search configurable product with product name"/> + <severity value="MAJOR"/> + <testCaseId value="MC-138"/> + <group value="CatalogSearch"/> + </annotations> + </test> + <test name="AdvanceCatalogSearchConfigurableBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search configurable product with product sku"/> + <description value="Guest customer should be able to advance search configurable product with product sku"/> + <severity value="MAJOR"/> + <testCaseId value="MC-144"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByProductSkuActionGroup" stepKey="search"> + <argument name="sku" value="$$createProductOne.sku$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchConfigurableByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search configurable product with product description"/> + <description value="Guest customer should be able to advance search configurable product with product description"/> + <severity value="MAJOR"/> + <testCaseId value="MC-237"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByDescriptionActionGroup" stepKey="search"> + <argument name="description" value="$$createProductOne.custom_attributes[description]$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchConfigurableByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search configurable product with product short description"/> + <description value="Guest customer should be able to advance search configurable product with product short description"/> + <severity value="MAJOR"/> + <testCaseId value="MC-240"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByShortDescriptionActionGroup" stepKey="search"> + <argument name="shortDescription" value="$$createProductOne.custom_attributes[short_description]$$"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchSimpleProductsTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchSimpleProductTest.xml similarity index 60% rename from dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchSimpleProductsTest.xml rename to dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchSimpleProductTest.xml index f52a86810842e..dbe225c24debc 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchSimpleProductsTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchSimpleProductTest.xml @@ -18,21 +18,15 @@ <testCaseId value="MC-132"/> <group value="CatalogSearch"/> </annotations> - <before> - <createData entity="ApiProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> <actionGroup ref="StorefrontAdvancedCatalogSearchByProductNameActionGroup" stepKey="search"> <argument name="name" value="$$createProductOne.name$$"/> </actionGroup> <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> + <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> </test> - <test name="AdvanceCatalogSearchSimpleProductBySkuTest"> + <test name="AdvanceCatalogSearchSimpleProductBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> <annotations> <features value="CatalogSearch"/> <stories value="Advanced Catalog Product Search for all product types"/> @@ -42,23 +36,11 @@ <testCaseId value="MC-133"/> <group value="CatalogSearch"/> </annotations> - <before> - <createData entity="ApiProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> <actionGroup ref="StorefrontAdvancedCatalogSearchByProductSkuActionGroup" stepKey="search"> <argument name="sku" value="$$createProductOne.sku$$"/> </actionGroup> - <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> - <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> - <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> </test> - - <test name="AdvanceCatalogSearchSimpleProductByDescriptionTest"> + <test name="AdvanceCatalogSearchSimpleProductByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> <annotations> <features value="CatalogSearch"/> <stories value="Advanced Catalog Product Search for all product types"/> @@ -68,23 +50,11 @@ <testCaseId value="MC-134"/> <group value="CatalogSearch"/> </annotations> - <before> - <createData entity="ApiProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> <actionGroup ref="StorefrontAdvancedCatalogSearchByDescriptionActionGroup" stepKey="search"> <argument name="description" value="$$createProductOne.custom_attributes[description]$$"/> </actionGroup> - <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> - <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> - <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> </test> - - <test name="AdvanceCatalogSearchSimpleProductByShortDescriptionTest"> + <test name="AdvanceCatalogSearchSimpleProductByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> <annotations> <features value="CatalogSearch"/> <stories value="Advanced Catalog Product Search for all product types"/> @@ -94,23 +64,11 @@ <testCaseId value="MC-135"/> <group value="CatalogSearch"/> </annotations> - <before> - <createData entity="ApiProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> <actionGroup ref="StorefrontAdvancedCatalogSearchByShortDescriptionActionGroup" stepKey="search"> <argument name="shortDescription" value="$$createProductOne.custom_attributes[short_description]$$"/> </actionGroup> - <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> - <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> - <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> </test> - - <test name="AdvanceCatalogSearchSimpleProductByPriceTest"> + <test name="AdvanceCatalogSearchSimpleProductByPriceTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> <annotations> <features value="CatalogSearch"/> <stories value="Advanced Catalog Product Search for all product types"/> @@ -120,21 +78,10 @@ <testCaseId value="MC-136"/> <group value="CatalogSearch"/> </annotations> - <before> - <createData entity="ApiProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> <actionGroup ref="StorefrontAdvancedCatalogSearchByProductNameAndPriceActionGroup" stepKey="search"> <argument name="name" value="$$createProductOne.name$$"/> <argument name="priceFrom" value="$$createProductOne.price$$"/> <argument name="priceTo" value="$$createProductOne.price$$"/> </actionGroup> - <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> - <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> - <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> </test> </tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchVirtualProductTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchVirtualProductTest.xml new file mode 100644 index 0000000000000..98bc7f01a6a00 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchVirtualProductTest.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdvanceCatalogSearchVirtualProductByNameTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search virtual product with product name"/> + <description value="Guest customer should be able to advance search virtual product with product name"/> + <severity value="MAJOR"/> + <testCaseId value="MC-137"/> + <group value="CatalogSearch"/> + </annotations> + </test> + <test name="AdvanceCatalogSearchVirtualProductBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search virtual product with product sku"/> + <description value="Guest customer should be able to advance search virtual product with product sku"/> + <severity value="MAJOR"/> + <testCaseId value="MC-162"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByProductSkuActionGroup" stepKey="search"> + <argument name="sku" value="$$createProductOne.sku$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchVirtualProductByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search virtual product with product description"/> + <description value="Guest customer should be able to advance search virtual product with product description"/> + <severity value="MAJOR"/> + <testCaseId value="MC-163"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByDescriptionActionGroup" stepKey="search"> + <argument name="description" value="$$createProductOne.custom_attributes[description]$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchVirtualProductByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search virtual product with product short description"/> + <description value="Guest customer should be able to advance search virtual product with product short description"/> + <severity value="MAJOR"/> + <testCaseId value="MC-164"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByShortDescriptionActionGroup" stepKey="search"> + <argument name="shortDescription" value="$$createProductOne.custom_attributes[short_description]$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchVirtualProductByPriceTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search virtual product with product price"/> + <description value="Guest customer should be able to advance search virtual product with product price"/> + <severity value="MAJOR"/> + <testCaseId value="MC-165"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByProductNameAndPriceActionGroup" stepKey="search"> + <argument name="name" value="$$createProductOne.name$$"/> + <argument name="priceFrom" value="$$createProductOne.price$$"/> + <argument name="priceTo" value="$$createProductOne.price$$"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchVirtualProductsTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchVirtualProductsTest.xml deleted file mode 100644 index 80b1b294fecd5..0000000000000 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchVirtualProductsTest.xml +++ /dev/null @@ -1,141 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> - <test name="AdvanceCatalogSearchVirtualProductByNameTest"> - <annotations> - <features value="CatalogSearch"/> - <stories value="Advanced Catalog Product Search for all product types"/> - <title value="Guest customer should be able to advance search virtual product with product name"/> - <description value="Guest customer should be able to advance search virtual product with product name"/> - <severity value="MAJOR"/> - <testCaseId value="MC-137"/> - <group value="CatalogSearch"/> - </annotations> - <before> - <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> - <actionGroup ref="StorefrontAdvancedCatalogSearchByProductNameActionGroup" stepKey="search"> - <argument name="name" value="$$createProductOne.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> - <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> - <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> - </test> - <test name="AdvanceCatalogSearchVirtualProductBySkuTest"> - <annotations> - <features value="CatalogSearch"/> - <stories value="Advanced Catalog Product Search for all product types"/> - <title value="Guest customer should be able to advance search virtual product with product sku"/> - <description value="Guest customer should be able to advance search virtual product with product sku"/> - <severity value="MAJOR"/> - <testCaseId value="MC-162"/> - <group value="CatalogSearch"/> - </annotations> - <before> - <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> - <actionGroup ref="StorefrontAdvancedCatalogSearchByProductSkuActionGroup" stepKey="search"> - <argument name="sku" value="$$createProductOne.sku$$"/> - </actionGroup> - <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> - <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> - <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> - </test> - - <test name="AdvanceCatalogSearchVirtualProductByDescriptionTest"> - <annotations> - <features value="CatalogSearch"/> - <stories value="Advanced Catalog Product Search for all product types"/> - <title value="Guest customer should be able to advance search virtual product with product description"/> - <description value="Guest customer should be able to advance search virtual product with product description"/> - <severity value="MAJOR"/> - <testCaseId value="MC-163"/> - <group value="CatalogSearch"/> - </annotations> - <before> - <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> - <actionGroup ref="StorefrontAdvancedCatalogSearchByDescriptionActionGroup" stepKey="search"> - <argument name="description" value="$$createProductOne.custom_attributes[description]$$"/> - </actionGroup> - <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> - <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> - <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> - </test> - - <test name="AdvanceCatalogSearchVirtualProductByShortDescriptionTest"> - <annotations> - <features value="CatalogSearch"/> - <stories value="Advanced Catalog Product Search for all product types"/> - <title value="Guest customer should be able to advance search virtual product with product short description"/> - <description value="Guest customer should be able to advance search virtual product with product short description"/> - <severity value="MAJOR"/> - <testCaseId value="MC-164"/> - <group value="CatalogSearch"/> - </annotations> - <before> - <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> - <actionGroup ref="StorefrontAdvancedCatalogSearchByShortDescriptionActionGroup" stepKey="search"> - <argument name="shortDescription" value="$$createProductOne.custom_attributes[short_description]$$"/> - </actionGroup> - <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> - <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> - <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> - </test> - - <test name="AdvanceCatalogSearchVirtualProductByPriceTest"> - <annotations> - <features value="CatalogSearch"/> - <stories value="Advanced Catalog Product Search for all product types"/> - <title value="Guest customer should be able to advance search virtual product with product price"/> - <description value="Guest customer should be able to advance search virtual product with product price"/> - <severity value="MAJOR"/> - <testCaseId value="MC-165"/> - <group value="CatalogSearch"/> - </annotations> - <before> - <createData entity="ApiVirtualProductWithDescription" stepKey="createProductOne"/> - </before> - <after> - <deleteData createDataKey="createProductOne" stepKey="deleteProductOne"/> - </after> - - <actionGroup ref="GoToStoreViewAdvancedCatalogSearchActionGroup" stepKey="GoToStoreViewAdvancedCatalogSearchActionGroup"/> - <actionGroup ref="StorefrontAdvancedCatalogSearchByProductNameAndPriceActionGroup" stepKey="search"> - <argument name="name" value="$$createProductOne.name$$"/> - <argument name="priceFrom" value="$$createProductOne.price$$"/> - <argument name="priceTo" value="$$createProductOne.price$$"/> - </actionGroup> - <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="StorefrontCheckAdvancedSearchResult"/> - <see userInput="1 item" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.itemFound}}" stepKey="see"/> - <see userInput="$$createProductOne.name$$" selector="{{StorefrontCatalogSearchAdvancedResultMainSection.productName}}" stepKey="seeProductName"/> - </test> -</tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Data/ConfigurableProductData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Data/ConfigurableProductData.xml index 0a2429fa8f9e5..70e758a51409d 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Data/ConfigurableProductData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Data/ConfigurableProductData.xml @@ -34,6 +34,19 @@ <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> + <entity name="ApiConfigurableProductWithDescription" type="product"> + <data key="sku" unique="suffix">api-configurable-product</data> + <data key="type_id">configurable</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="name" unique="suffix">API Configurable Product</data> + <data key="urlKey" unique="suffix">api-configurable-product</data> + <data key="status">1</data> + <data key="quantity">100</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute_array">ApiProductDescription</requiredEntity> + <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> + </entity> <entity name="ConfigurableProductAddChild" type="ConfigurableProductAddChild"> <var key="sku" entityKey="sku" entityType="product" /> <var key="childSku" entityKey="sku" entityType="product2"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/AdvanceCatalogSearchConfigurableTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/AdvanceCatalogSearchConfigurableTest.xml new file mode 100644 index 0000000000000..65760b5e72308 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/AdvanceCatalogSearchConfigurableTest.xml @@ -0,0 +1,267 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdvanceCatalogSearchConfigurableByNameTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="SimpleSubCategory" stepKey="categoryHandle" before="simple1Handle"/> + + <createData entity="SimpleProduct" stepKey="simple1Handle" before="simple2Handle"> + <requiredEntity createDataKey="categoryHandle"/> + </createData> + + <createData entity="SimpleProduct" stepKey="simple2Handle" before="createProductOne"> + <requiredEntity createDataKey="categoryHandle"/> + </createData> + + <!-- TODO: Move configurable product creation to an actionGroup when MQE-697 is fixed --> + <createData entity="ApiConfigurableProductWithDescription" stepKey="createProductOne"/> + + <createData entity="productDropDownAttribute" stepKey="productAttributeHandle"/> + + <createData entity="productAttributeOption1" stepKey="productAttributeOption1Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + <createData entity="productAttributeOption2" stepKey="productAttributeOption2Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + + <createData entity="AddToDefaultSet" stepKey="addToAttributeSetHandle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getAttributeOption1Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getAttributeOption2Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </getData> + + <createData entity="SimpleOne" stepKey="childProductHandle1"> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption1Handle"/> + </createData> + <createData entity="SimpleOne" stepKey="childProductHandle2"> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption2Handle"/> + </createData> + + <createData entity="ConfigurableProductTwoOptions" stepKey="configProductOptionHandle"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption1Handle"/> + <requiredEntity createDataKey="getAttributeOption2Handle"/> + </createData> + + <createData entity="ConfigurableProductAddChild" stepKey="configProductHandle1"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="childProductHandle1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="configProductHandle2"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="childProductHandle2"/> + </createData> + </before> + </test> + <test name="AdvanceCatalogSearchConfigurableBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="SimpleSubCategory" stepKey="categoryHandle" before="simple1Handle"/> + + <createData entity="SimpleProduct" stepKey="simple1Handle" before="simple2Handle"> + <requiredEntity createDataKey="categoryHandle"/> + </createData> + + <createData entity="SimpleProduct" stepKey="simple2Handle" before="createProductOne"> + <requiredEntity createDataKey="categoryHandle"/> + </createData> + + <!-- TODO: Move configurable product creation to an actionGroup when MQE-697 is fixed --> + <createData entity="ApiConfigurableProductWithDescription" stepKey="createProductOne"/> + + <createData entity="productDropDownAttribute" stepKey="productAttributeHandle"/> + + <createData entity="productAttributeOption1" stepKey="productAttributeOption1Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + <createData entity="productAttributeOption2" stepKey="productAttributeOption2Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + + <createData entity="AddToDefaultSet" stepKey="addToAttributeSetHandle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getAttributeOption1Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getAttributeOption2Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </getData> + + <createData entity="SimpleOne" stepKey="childProductHandle1"> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption1Handle"/> + </createData> + <createData entity="SimpleOne" stepKey="childProductHandle2"> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption2Handle"/> + </createData> + + <createData entity="ConfigurableProductTwoOptions" stepKey="configProductOptionHandle"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption1Handle"/> + <requiredEntity createDataKey="getAttributeOption2Handle"/> + </createData> + + <createData entity="ConfigurableProductAddChild" stepKey="configProductHandle1"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="childProductHandle1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="configProductHandle2"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="childProductHandle2"/> + </createData> + </before> + </test> + <test name="AdvanceCatalogSearchConfigurableByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="SimpleSubCategory" stepKey="categoryHandle" before="simple1Handle"/> + + <createData entity="SimpleProduct" stepKey="simple1Handle" before="simple2Handle"> + <requiredEntity createDataKey="categoryHandle"/> + </createData> + + <createData entity="SimpleProduct" stepKey="simple2Handle" before="createProductOne"> + <requiredEntity createDataKey="categoryHandle"/> + </createData> + + <!-- TODO: Move configurable product creation to an actionGroup when MQE-697 is fixed --> + <createData entity="ApiConfigurableProductWithDescription" stepKey="createProductOne"/> + + <createData entity="productDropDownAttribute" stepKey="productAttributeHandle"/> + + <createData entity="productAttributeOption1" stepKey="productAttributeOption1Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + <createData entity="productAttributeOption2" stepKey="productAttributeOption2Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + + <createData entity="AddToDefaultSet" stepKey="addToAttributeSetHandle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getAttributeOption1Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getAttributeOption2Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </getData> + + <createData entity="SimpleOne" stepKey="childProductHandle1"> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption1Handle"/> + </createData> + <createData entity="SimpleOne" stepKey="childProductHandle2"> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption2Handle"/> + </createData> + + <createData entity="ConfigurableProductTwoOptions" stepKey="configProductOptionHandle"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption1Handle"/> + <requiredEntity createDataKey="getAttributeOption2Handle"/> + </createData> + + <createData entity="ConfigurableProductAddChild" stepKey="configProductHandle1"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="childProductHandle1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="configProductHandle2"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="childProductHandle2"/> + </createData> + </before> + </test> + <test name="AdvanceCatalogSearchConfigurableByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="SimpleSubCategory" stepKey="categoryHandle" before="simple1Handle"/> + + <createData entity="SimpleProduct" stepKey="simple1Handle" before="simple2Handle"> + <requiredEntity createDataKey="categoryHandle"/> + </createData> + + <createData entity="SimpleProduct" stepKey="simple2Handle" before="createProductOne"> + <requiredEntity createDataKey="categoryHandle"/> + </createData> + + <!-- TODO: Move configurable product creation to an actionGroup when MQE-697 is fixed --> + <createData entity="ApiConfigurableProductWithDescription" stepKey="createProductOne"/> + + <createData entity="productDropDownAttribute" stepKey="productAttributeHandle"/> + + <createData entity="productAttributeOption1" stepKey="productAttributeOption1Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + <createData entity="productAttributeOption2" stepKey="productAttributeOption2Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + + <createData entity="AddToDefaultSet" stepKey="addToAttributeSetHandle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </createData> + + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getAttributeOption1Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getAttributeOption2Handle"> + <requiredEntity createDataKey="productAttributeHandle"/> + </getData> + + <createData entity="SimpleOne" stepKey="childProductHandle1"> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption1Handle"/> + </createData> + <createData entity="SimpleOne" stepKey="childProductHandle2"> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption2Handle"/> + </createData> + + <createData entity="ConfigurableProductTwoOptions" stepKey="configProductOptionHandle"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="productAttributeHandle"/> + <requiredEntity createDataKey="getAttributeOption1Handle"/> + <requiredEntity createDataKey="getAttributeOption2Handle"/> + </createData> + + <createData entity="ConfigurableProductAddChild" stepKey="configProductHandle1"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="childProductHandle1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="configProductHandle2"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="childProductHandle2"/> + </createData> + </before> + </test> +</tests> From b7252a2ca55549d7076429dc18aad28170ca3c34 Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@magento.com> Date: Wed, 30 May 2018 15:49:07 -0500 Subject: [PATCH 0872/2023] MC-142: Guest customer should be able to advance search downloadable product with product name MC-252: Guest customer should be able to advance search downloadable product with product sku MC-243: Guest customer should be able to advance search downloadable product with product description MC-245: Guest customer should be able to advance search downloadable product with product short description MC-246: Guest customer should be able to advance search downloadable product with product price - added mftf tests --- ...ceCatalogSearchDownloadableProductTest.xml | 80 +++++++++++++++++ .../Downloadable/Data/LinkData.xml | 9 ++ .../Downloadable/Data/ProductData.xml | 15 ++++ .../Metadata/downloadable_link-meta.xml | 31 +++++++ .../Metadata/link_file_content-meta.xml | 15 ++++ .../Metadata/sample_file_content-meta.xml | 15 ++++ ...ceCatalogSearchDownloadableProductTest.xml | 86 +++++++++++++++++++ 7 files changed, 251 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchDownloadableProductTest.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/downloadable_link-meta.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/link_file_content-meta.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/sample_file_content-meta.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Test/AdvanceCatalogSearchDownloadableProductTest.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchDownloadableProductTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchDownloadableProductTest.xml new file mode 100644 index 0000000000000..bfb96dd23f06b --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchDownloadableProductTest.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdvanceCatalogSearchDownloadableByNameTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Downloadable product with product name"/> + <description value="Guest customer should be able to advance search Downloadable product with product name"/> + <severity value="MAJOR"/> + <testCaseId value="MC-142"/> + <group value="CatalogSearch"/> + </annotations> + </test> + <test name="AdvanceCatalogSearchDownloadableBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Downloadable product with product sku"/> + <description value="Guest customer should be able to advance search Downloadable product with product sku"/> + <severity value="MAJOR"/> + <testCaseId value="MC-252"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByProductSkuActionGroup" stepKey="search"> + <argument name="sku" value="$$createProductOne.sku$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchDownloadableByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Downloadable product with product description"/> + <description value="Guest customer should be able to advance search Downloadable product with product description"/> + <severity value="MAJOR"/> + <testCaseId value="MC-243"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByDescriptionActionGroup" stepKey="search"> + <argument name="description" value="$$createProductOne.custom_attributes[description]$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchDownloadableByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Downloadable product with product short description"/> + <description value="Guest customer should be able to advance search Downloadable product with product short description"/> + <severity value="MAJOR"/> + <testCaseId value="MC-245"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByShortDescriptionActionGroup" stepKey="search"> + <argument name="shortDescription" value="$$createProductOne.custom_attributes[short_description]$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchDownloadableByPriceTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Downloadable product with product price"/> + <description value="Guest customer should be able to advance search Downloadable product with product price"/> + <severity value="MAJOR"/> + <testCaseId value="MC-246"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByProductNameAndPriceActionGroup" stepKey="search"> + <argument name="name" value="$$createProductOne.name$$"/> + <argument name="priceFrom" value="$$createProductOne.price$$"/> + <argument name="priceTo" value="$$createProductOne.price$$"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/LinkData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/LinkData.xml index 6276f340f85a6..5099255b3a1f7 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/LinkData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/LinkData.xml @@ -41,4 +41,13 @@ <data key="file_type">URL</data> <data key="file">https://static.magento.com/sites/all/themes/mag_redesign/images/magento-logo.svg</data> </entity> + <entity name="ApiDownloadableLink" type="downloadable_link"> + <data key="title" unique="suffix">Api Downloadable Link</data> + <data key="price">2.00</data> + <data key="link_type">url</data> + <data key="shareable">No</data> + <data key="number_of_downloads">1000</data> + <data key="sort_order">0</data> + <data key="link_file">https://static.magento.com/sites/all/themes/mag_redesign/images/magento-logo.svg</data> + </entity> </entities> \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/ProductData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/ProductData.xml index 427f2577a8ab9..f71ebd481a97d 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/ProductData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/ProductData.xml @@ -19,4 +19,19 @@ <data key="status">1</data> <data key="urlKey" unique="suffix">downloadableproduct</data> </entity> + <entity name="ApiDownloadableProduct" type="product"> + <data key="sku" unique="suffix">api-downloadable-product</data> + <data key="type_id">downloadable</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="name" unique="suffix">Api Downloadable Product</data> + <data key="price">123.00</data> + <data key="urlKey" unique="suffix">api-downloadable-product</data> + <data key="status">1</data> + <data key="quantity">100</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute_array">ApiProductDescription</requiredEntity> + <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> + <requiredEntity type="downloadable_link">apiDownloadableLink</requiredEntity> + </entity> </entities> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/downloadable_link-meta.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/downloadable_link-meta.xml new file mode 100644 index 0000000000000..dc86c4e8d7957 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/downloadable_link-meta.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd"> + <operation name="CreateDownloadableLink" dataType="downloadable_link" type="create" auth="adminOauth" url="/V1/products/{sku}/downloadable-links" method="POST"> + <contentType>application/json</contentType> + <object dataType="downloadable_link" key="link"> + <field key="title">string</field> + <field key="sort_order">integer</field> + <field key="is_shareable">integer</field> + <field key="price">number</field> + <field key="number_of_downloads">integer</field> + <field key="link_type">string</field> + <field key="link_file">string</field> + <field key="link_file_content">link_file_content</field> + <field key="file_data">string</field> + <field key="link_url">string</field> + <field key="sample_type">string</field> + <field key="sample_file">string</field> + <field key="sample_file_content">sample_file_content</field> + <field key="sample_url">string</field> + </object> + <field key="isGlobalScopeContent">boolean</field> + </operation> +</operations> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/link_file_content-meta.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/link_file_content-meta.xml new file mode 100644 index 0000000000000..72f643e06800d --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/link_file_content-meta.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd"> + <operation name="CreateLinkFileContent" dataType="link_file_content" type="create"> + <field key="file_data">string</field> + <field key="name">string</field> + </operation> +</operations> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/sample_file_content-meta.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/sample_file_content-meta.xml new file mode 100644 index 0000000000000..144ce67bb25bb --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Metadata/sample_file_content-meta.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd"> + <operation name="CreateSampleFileContent" dataType="sample_file_content" type="create"> + <field key="file_data">string</field> + <field key="name">string</field> + </operation> +</operations> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Test/AdvanceCatalogSearchDownloadableProductTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Test/AdvanceCatalogSearchDownloadableProductTest.xml new file mode 100644 index 0000000000000..ef8fcf66e92de --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Test/AdvanceCatalogSearchDownloadableProductTest.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdvanceCatalogSearchDownloadableByNameTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> + <!-- Uncomment after bug MQE-1023 is fixed --> + <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> + <requiredEntity createDataKey="createProductOne"/> + </createData--> + </before> + </test> + <test name="AdvanceCatalogSearchDownloadableBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> + <!-- Uncomment after bug MQE-1023 is fixed --> + <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> + <requiredEntity createDataKey="createProductOne"/> + </createData--> + </before> + </test> + <test name="AdvanceCatalogSearchDownloadableByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> + <!-- Uncomment after bug MQE-1023 is fixed --> + <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> + <requiredEntity createDataKey="createProductOne"/> + </createData--> + </before> + </test> + <test name="AdvanceCatalogSearchDownloadableByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> + <!-- Uncomment after bug MQE-1023 is fixed --> + <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> + <requiredEntity createDataKey="createProductOne"/> + </createData--> + </before> + </test> + <test name="AdvanceCatalogSearchDownloadableByPriceTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> + <!-- Uncomment after bug MQE-1023 is fixed --> + <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> + <requiredEntity createDataKey="createProductOne"/> + </createData--> + </before> + </test> +</tests> From 8e8d0d2e2351fd9b2dbf1937156b0264440c4394 Mon Sep 17 00:00:00 2001 From: Alex Paliarush <apaliarush@magento.com> Date: Wed, 30 May 2018 19:31:18 -0500 Subject: [PATCH 0873/2023] ENGCOM-1663: Include 'products' in category query #48 --- .../Catalog/_files/categories_indexed.php | 19 ++++++++----------- .../_files/categories_indexed_rollback.php | 19 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php index f76370978404d..ff444813a9d07 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php @@ -3,19 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); include __DIR__ . '/categories.php'; $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); -/** @var \Magento\Catalog\Model\Indexer\Category\Product\Processor $categoryProductIndexer */ -$categoryProductIndexer = $objectManager->get( - \Magento\Catalog\Model\Indexer\Category\Product\Processor::class -); -$categoryProductIndexer->reindexAll(); - -/** @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor $inventoryIndexer */ -$inventoryIndexer = $objectManager->get( - \Magento\CatalogInventory\Model\Indexer\Stock\Processor::class -); -$inventoryIndexer->reindexAll(); +/** @var \Magento\Indexer\Model\Indexer\CollectionFactory $indexerCollectionFactory */ +$indexerCollectionFactory = $objectManager->get(\Magento\Indexer\Model\Indexer\CollectionFactory::class); +$indexerCollection = $indexerCollectionFactory->create(); +$indexers = $indexerCollection->getItems(); +foreach ($indexers as $indexer) { + $indexer->reindexAll(); +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php index 573fb7c3a2b11..338a4b23bee59 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php @@ -3,19 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); include __DIR__ . '/categories_rollback.php'; $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); -/** @var \Magento\Catalog\Model\Indexer\Category\Product\Processor $categoryProductIndexer */ -$categoryProductIndexer = $objectManager->get( - \Magento\Catalog\Model\Indexer\Category\Product\Processor::class -); -$categoryProductIndexer->reindexAll(); - -/** @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor $inventoryIndexer */ -$inventoryIndexer = $objectManager->get( - \Magento\CatalogInventory\Model\Indexer\Stock\Processor::class -); -$inventoryIndexer->reindexAll(); +/** @var \Magento\Indexer\Model\Indexer\CollectionFactory $indexerCollectionFactory */ +$indexerCollectionFactory = $objectManager->get(\Magento\Indexer\Model\Indexer\CollectionFactory::class); +$indexerCollection = $indexerCollectionFactory->create(); +$indexers = $indexerCollection->getItems(); +foreach ($indexers as $indexer) { + $indexer->reindexAll(); +} From 6a5125f6235a9077b8a7ade5996b9d0dd85587e1 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@magento.com> Date: Wed, 30 May 2018 22:20:16 -0500 Subject: [PATCH 0874/2023] MAGETWO-91545: Error not found page issue in change status and update attribute from product grid - added functional test to cover the usecase --- .../Analytics/Data/UserData.xml | 11 ++++++++++ .../Analytics/Data/UserRoleData.xml | 20 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserData.xml index 65ddfa7bb9559..4296974bc06e8 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserData.xml @@ -19,4 +19,15 @@ <data key="is_active">true</data> <data key="current_password">123123q</data> </entity> + <entity name="restrictedCatalogProductUser" type="user"> + <data key="username" unique="suffix">restrictedUser</data> + <data key="firstname">RestrictedCatalogUser</data> + <data key="lastname">Product</data> + <data key="email" unique="prefix">restrictedCatalogUser@example.com</data> + <data key="password">123123q</data> + <data key="password_confirmation">123123q</data> + <data key="interface_local">en_US</data> + <data key="is_active">true</data> + <data key="current_password">123123q</data> + </entity> </entities> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserRoleData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserRoleData.xml index 162b477ff68fb..f6a0dcc21f813 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserRoleData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Analytics/Data/UserRoleData.xml @@ -11,6 +11,10 @@ <entity name="adminNoReportRole" type="user_role"> <data key="rolename" unique="suffix">noreport</data> <data key="current_password">123123q</data> + <!--<data key="gws_is_all">0</data>--> + <!--<array key="gws_websites">--> + <!--<item>1</item>--> + <!--</array>--> <array key="resource"> <item>Magento_Backend::dashboard</item> <item>Magento_Sales::sales</item> @@ -168,4 +172,20 @@ <item>Magento_Backend::global_search</item> </array> </entity> + <entity name="adminCatalogProductRole" type="user_role"> + <data key="rolename" unique="suffix">restrictedRole</data> + <data key="current_password">123123q</data> + <data key="gws_is_all">0</data> + <array key="gws_websites"> + <item>1</item> + </array> + <array key="resource"> + <item>Magento_Catalog::catalog</item> + <item>Magento_Catalog::catalog_inventory</item> + <item>Magento_Catalog::products</item> + <item>Magento_PricePermissions::read_product_price</item> + <item>Magento_PricePermissions::edit_product_price</item> + <item>Magento_PricePermissions::edit_product_status</item> + </array> + </entity> </entities> From 18fe48c2ff20110c84ef13fd867a50d7ecd6b75e Mon Sep 17 00:00:00 2001 From: Alex Paliarush <apaliarush@magento.com> Date: Wed, 30 May 2018 20:25:15 -0500 Subject: [PATCH 0875/2023] ENGCOM-1663: Include 'products' in category query #48 --- .../Magento/GraphQl/Catalog/CategoryTest.php | 18 ++++++------------ .../Catalog/_files/categories_indexed.php | 18 ------------------ .../_files/categories_indexed_rollback.php | 18 ------------------ 3 files changed, 6 insertions(+), 48 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php delete mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php index d82b15e3990e9..223fa75006d45 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php @@ -114,13 +114,12 @@ public function testCategoriesTree() } /** - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Catalog/_files/categories_indexed.php + * @magentoApiDataFixture Magento/Catalog/_files/categories.php * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testCategoryProducts() { - $categoryId = 4; + $categoryId = 2; $query = <<<QUERY { category(id: {$categoryId}) { @@ -266,25 +265,21 @@ public function testCategoryProducts() $response = $this->graphQlQuery($query); $this->assertArrayHasKey('products', $response['category']); $this->assertArrayHasKey('total_count', $response['category']['products']); - $this->assertEquals(2, $response['category']['products']['total_count']); + $this->assertGreaterThanOrEqual(1, $response['category']['products']['total_count']); $this->assertEquals(1, $response['category']['products']['page_info']['current_page']); $this->assertEquals(20, $response['category']['products']['page_info']['page_size']); + $this->assertArrayHasKey('sku', $response['category']['products']['items'][0]); + $firstProductSku = $response['category']['products']['items'][0]['sku']; + /** * @var ProductRepositoryInterface $productRepository */ $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); - $firstProductSku = 'simple'; $firstProduct = $productRepository->get($firstProductSku, false, null, true); $this->assertBaseFields($firstProduct, $response['category']['products']['items'][0]); $this->assertAttributes($response['category']['products']['items'][0]); $this->assertWebsites($firstProduct, $response['category']['products']['items'][0]['websites']); - - $secondProductSku = '12345'; - $secondProduct = $productRepository->get($secondProductSku, false, null, true); - $this->assertBaseFields($secondProduct, $response['category']['products']['items'][1]); - $this->assertAttributes($response['category']['products']['items'][1]); - $this->assertWebsites($secondProduct, $response['category']['products']['items'][1]['websites']); } /** @@ -297,7 +292,6 @@ private function assertBaseFields($product, $actualResponse) $assertionMap = [ ['response_field' => 'attribute_set_id', 'expected_value' => $product->getAttributeSetId()], ['response_field' => 'created_at', 'expected_value' => $product->getCreatedAt()], - ['response_field' => 'id', 'expected_value' => $product->getId()], ['response_field' => 'name', 'expected_value' => $product->getName()], ['response_field' => 'price', 'expected_value' => [ diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php deleted file mode 100644 index ff444813a9d07..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -include __DIR__ . '/categories.php'; - -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - -/** @var \Magento\Indexer\Model\Indexer\CollectionFactory $indexerCollectionFactory */ -$indexerCollectionFactory = $objectManager->get(\Magento\Indexer\Model\Indexer\CollectionFactory::class); -$indexerCollection = $indexerCollectionFactory->create(); -$indexers = $indexerCollection->getItems(); -foreach ($indexers as $indexer) { - $indexer->reindexAll(); -} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php deleted file mode 100644 index 338a4b23bee59..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories_indexed_rollback.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -include __DIR__ . '/categories_rollback.php'; - -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - -/** @var \Magento\Indexer\Model\Indexer\CollectionFactory $indexerCollectionFactory */ -$indexerCollectionFactory = $objectManager->get(\Magento\Indexer\Model\Indexer\CollectionFactory::class); -$indexerCollection = $indexerCollectionFactory->create(); -$indexers = $indexerCollection->getItems(); -foreach ($indexers as $indexer) { - $indexer->reindexAll(); -} From 3ac2c28ecb0e70452993001eafd417936cb44c48 Mon Sep 17 00:00:00 2001 From: Stanislav Lopukhov <slopukhov@magento.com> Date: Thu, 31 May 2018 08:50:56 +0300 Subject: [PATCH 0876/2023] MAGETWO-92306: [Forwardport] Fix Category Product Indexer --- .../Model/Indexer/Category/Product/TableMaintainer.php | 8 ++++++++ app/code/Magento/Catalog/etc/adminhtml/di.xml | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Product/TableMaintainer.php b/app/code/Magento/Catalog/Model/Indexer/Category/Product/TableMaintainer.php index d2f8925d09a7b..1278434fcad43 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Category/Product/TableMaintainer.php +++ b/app/code/Magento/Catalog/Model/Indexer/Category/Product/TableMaintainer.php @@ -13,6 +13,9 @@ use Magento\Catalog\Model\Indexer\Category\Product\AbstractAction; use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver as TableResolver; +/** + * Class encapsulate logic of work with tables per store in Category Product indexer + */ class TableMaintainer { /** @@ -202,9 +205,14 @@ public function createMainTmpTable(int $storeId) * @param $storeId * * @return string + * + * @throws \Exception */ public function getMainTmpTable(int $storeId) { + if (!isset($this->mainTmpTable[$storeId])) { + throw new \Exception('Temporary table does not exist'); + } return $this->mainTmpTable[$storeId]; } } diff --git a/app/code/Magento/Catalog/etc/adminhtml/di.xml b/app/code/Magento/Catalog/etc/adminhtml/di.xml index ca8390a6c8f8a..10251d35dffcd 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/di.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/di.xml @@ -220,7 +220,4 @@ <argument name="filter" xsi:type="object">Magento\Catalog\Ui\DataProvider\Product\AddSearchKeyConditionToCollection</argument> </arguments> </type> - <type name="Magento\Framework\App\ResourceConnection"> - <plugin name="get_catalog_category_product_index_table_name" type="Magento\Catalog\Model\Indexer\Category\Product\Plugin\TableResolver"/> - </type> </config> From 6a0e8cbf0ba1f08a94140b7346be00ca95243890 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 31 May 2018 09:59:03 +0300 Subject: [PATCH 0877/2023] MAGETWO-66217: Product Url key value comes from product name on storeview level (use default = yes) --- .../Initialization/Helper/AttributeFilter.php | 12 ++++++------ .../Initialization/Helper/AttributeFilterTest.php | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index 09af738a13201..188b0b22f33bf 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -51,7 +51,7 @@ public function prepareProductAttributes(Product $product, array $productData, a * @param array $productData * @return array */ - private function prepareConfigData(Product $product, $attributeCode, array $productData): array + private function prepareConfigData(Product $product, string $attributeCode, array $productData): array { // UI component sends value even if field is disabled, so 'Use Config Settings' must be reset to false if ($product->hasData('use_config_' . $attributeCode)) { @@ -67,7 +67,7 @@ private function prepareConfigData(Product $product, $attributeCode, array $prod * @param array $productData * @return array */ - private function prepareDefaultData(array $attributeList, $attributeCode, array $productData): array + private function prepareDefaultData(array $attributeList, string $attributeCode, array $productData): array { if (isset($attributeList[$attributeCode])) { /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */ @@ -87,12 +87,12 @@ private function prepareDefaultData(array $attributeList, $attributeCode, array /** * @param Product $product - * @param $useDefaults - * @param $attribute - * @param $value + * @param array $useDefaults + * @param string $attribute + * @param mixed $value * @return bool */ - private function isAttributeShouldNotBeUpdated(Product $product, $useDefaults, $attribute, $value): bool + private function isAttributeShouldNotBeUpdated(Product $product, array $useDefaults, $attribute, $value): bool { $considerUseDefaultsAttribute = !isset($useDefaults[$attribute]) || $useDefaults[$attribute] === '1'; diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilterTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilterTest.php index 6e25d02df53ee..424427b871456 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilterTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilterTest.php @@ -9,7 +9,7 @@ use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper\AttributeFilter; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; -use PHPUnit_Framework_MockObject_MockObject; +use PHPUnit_Framework_MockObject_MockObject as MockObject; class AttributeFilterTest extends \PHPUnit\Framework\TestCase { @@ -19,12 +19,12 @@ class AttributeFilterTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $objectManagerMock; /** - * @var Product|PHPUnit_Framework_MockObject_MockObject + * @var Product|MockObject */ protected $productMock; @@ -47,7 +47,7 @@ public function testPrepareProductAttributes( $expectedProductData, $initialProductData ) { - /** @var PHPUnit_Framework_MockObject_MockObject | Product $productMockMap */ + /** @var MockObject | Product $productMockMap */ $productMockMap = $this->getMockBuilder(Product::class) ->disableOriginalConstructor() ->setMethods(['getData', 'getAttributes']) @@ -225,7 +225,7 @@ private function getProductAttributesMock(array $useDefaults): array $returnArray = []; foreach ($useDefaults as $attributecode => $isDefault) { if ($isDefault === '1') { - /** @var Attribute | PHPUnit_Framework_MockObject_MockObject $attribute */ + /** @var Attribute | MockObject $attribute */ $attribute = $this->getMockBuilder(Attribute::class) ->disableOriginalConstructor() ->getMock(); From 483c8583ae2bd97c8cbe0117b9b092427b4604e0 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 31 May 2018 10:17:23 +0300 Subject: [PATCH 0878/2023] MAGETWO-91104: [2.3.0] Using a multiselect product attribute with a custom source model in the adminhtml doesn't render selected value --- .../Product/Form/Modifier/EavTest.php | 321 +++++++----------- .../Product/Form/Modifier/Eav.php | 20 +- 2 files changed, 151 insertions(+), 190 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php index a29379647b9e1..320ec821d7ffb 100755 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php @@ -5,11 +5,10 @@ */ namespace Magento\Catalog\Test\Unit\Ui\DataProvider\Product\Form\Modifier; -use Magento\Catalog\Model\Product\Type; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav; use Magento\Eav\Model\Config; +use Magento\Eav\Model\Entity\Attribute\Source\SourceInterface; use Magento\Framework\App\RequestInterface; -use Magento\Framework\EntityManager\EventManager; use Magento\Framework\Phrase; use Magento\Store\Model\StoreManagerInterface; use Magento\Store\Api\Data\StoreInterface; @@ -257,7 +256,15 @@ protected function setUp() $this->searchResultsMock = $this->getMockBuilder(SearchResultsInterface::class) ->getMockForAbstractClass(); $this->eavAttributeMock = $this->getMockBuilder(Attribute::class) - ->setMethods(['load', 'getAttributeGroupCode', 'getApplyTo', 'getFrontendInput', 'getAttributeCode']) + ->setMethods([ + 'load', + 'getAttributeGroupCode', + 'getApplyTo', + 'getFrontendInput', + 'getAttributeCode', + 'usesSource', + 'getSource', + ]) ->disableOriginalConstructor() ->getMock(); $this->productAttributeMock = $this->getMockBuilder(ProductAttributeInterface::class) @@ -451,64 +458,60 @@ public function testModifyData() } /** - * @param int $productId + * @param int|null $productId * @param bool $productRequired - * @param string $attrValue - * @param string $note + * @param string|null $attrValue * @param array $expected * @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::isProductExists * @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::setupAttributeMeta * @dataProvider setupAttributeMetaDataProvider */ - public function testSetupAttributeMetaDefaultAttribute($productId, $productRequired, $attrValue, $note, $expected) - { - $configPath = 'arguments/data/config'; + public function testSetupAttributeMetaDefaultAttribute( + $productId, + $productRequired, + $attrValue, + $expected + ) { + $configPath = 'arguments/data/config'; $groupCode = 'product-details'; $sortOrder = '0'; + $attributeOptions = [ + ['value' => 1, 'label' => 'Int label'], + ['value' => 1.5, 'label' => 'Float label'], + ['value' => true, 'label' => 'Boolean label'], + ['value' => 'string', 'label' => 'String label'], + ['value' => ['test1', 'test2'], 'label' => 'Array label'] + ]; + $attributeOptionsExpected = [ + ['value' => '1', 'label' => 'Int label'], + ['value' => '1.5', 'label' => 'Float label'], + ['value' => '1', 'label' => 'Boolean label'], + ['value' => 'string', 'label' => 'String label'], + ['value' => ['test1', 'test2'], 'label' => 'Array label'] + ]; - $this->productMock->expects($this->any()) - ->method('getId') - ->willReturn($productId); - - $this->productAttributeMock->expects($this->any()) - ->method('getIsRequired') - ->willReturn($productRequired); - - $this->productAttributeMock->expects($this->any()) - ->method('getDefaultValue') - ->willReturn('required_value'); - - $this->productAttributeMock->expects($this->any()) - ->method('getAttributeCode') - ->willReturn('code'); - - $this->productAttributeMock->expects($this->any()) - ->method('getValue') - ->willReturn('value'); - - $this->productAttributeMock->expects($this->any()) - ->method('getNote') - ->willReturn($note); - - $this->productAttributeMock->expects($this->any()) - ->method('getDefaultFrontendLabel') - ->willReturn(new Phrase('mylabel')); + $this->productMock->method('getId')->willReturn($productId); + $this->productAttributeMock->method('getIsRequired')->willReturn($productRequired); + $this->productAttributeMock->method('getDefaultValue')->willReturn('required_value'); + $this->productAttributeMock->method('getAttributeCode')->willReturn('code'); + $this->productAttributeMock->method('getValue')->willReturn('value'); $attributeMock = $this->getMockBuilder(AttributeInterface::class) ->setMethods(['getValue']) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $attributeMock->expects($this->any()) - ->method('getValue') - ->willReturn($attrValue); + $attributeMock->method('getValue')->willReturn($attrValue); - $this->productMock->expects($this->any()) - ->method('getCustomAttribute') - ->willReturn($attributeMock); + $this->productMock->method('getCustomAttribute')->willReturn($attributeMock); + $this->eavAttributeMock->method('usesSource')->willReturn(true); + + $attributeSource = $this->getMockBuilder(SourceInterface::class)->getMockForAbstractClass(); + $attributeSource->method('getAllOptions')->willReturn($attributeOptions); - $this->arrayManagerMock->expects($this->any()) - ->method('set') + $this->eavAttributeMock->method('getSource')->willReturn($attributeSource); + + $this->arrayManagerMock->method('set') ->with( $configPath, [], @@ -516,16 +519,21 @@ public function testSetupAttributeMetaDefaultAttribute($productId, $productRequi ) ->willReturn($expected); - $this->arrayManagerMock->expects($this->any()) + $this->arrayManagerMock->expects($this->once()) ->method('merge') + ->with( + $this->anything(), + $this->anything(), + $this->callback( + function ($value) use ($attributeOptionsExpected) { + return $value['options'] === $attributeOptionsExpected; + } + ) + ) ->willReturn($expected); - $this->arrayManagerMock->expects($this->any()) - ->method('get') - ->willReturn([]); - - $this->arrayManagerMock->expects($this->any()) - ->method('exists'); + $this->arrayManagerMock->method('get')->willReturn([]); + $this->arrayManagerMock->method('exists')->willReturn(true); $this->assertEquals( $expected, @@ -539,147 +547,82 @@ public function testSetupAttributeMetaDefaultAttribute($productId, $productRequi public function setupAttributeMetaDataProvider() { return [ - 'default_null_prod_not_new_and_required' => $this->defaultNullProdNotNewAndRequired(), - 'default_null_prod_not_new_and_not_required' => $this->defaultNullProdNotNewAndNotRequired(), - 'default_null_prod_new_and_not_required' => $this->defaultNullProdNewAndNotRequired(), - 'default_null_prod_new_and_required' => $this->defaultNullProdNewAndRequired(), - 'default_null_prod_new_and_required_and_filled_notice' => - $this->defaultNullProdNewAndRequiredAndFilledNotice() - ]; - } - - /** - * @return array - */ - private function defaultNullProdNotNewAndRequired() - { - return [ - 'productId' => 1, - 'productRequired' => true, - 'attrValue' => 'val', - 'note' => null, - 'expected' => [ - 'dataType' => null, - 'formElement' => null, - 'visible' => null, - 'required' => true, - 'notice' => null, - 'default' => null, - 'label' => new Phrase('mylabel'), - 'code' => 'code', - 'source' => 'product-details', - 'scopeLabel' => '', - 'globalScope' => false, - 'sortOrder' => 0 - ], - ]; - } - - /** - * @return array - */ - private function defaultNullProdNotNewAndNotRequired() - { - return [ - 'productId' => 1, - 'productRequired' => false, - 'attrValue' => 'val', - 'note' => null, - 'expected' => [ - 'dataType' => null, - 'formElement' => null, - 'visible' => null, - 'required' => false, - 'notice' => null, - 'default' => null, - 'label' => new Phrase('mylabel'), - 'code' => 'code', - 'source' => 'product-details', - 'scopeLabel' => '', - 'globalScope' => false, - 'sortOrder' => 0 + 'default_null_prod_not_new_and_required' => [ + 'productId' => 1, + 'productRequired' => true, + 'attrValue' => 'val', + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => true, + 'notice' => null, + 'default' => null, + 'label' => new Phrase(null), + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0 + ], ], - ]; - } - - /** - * @return array - */ - private function defaultNullProdNewAndNotRequired() - { - return [ - 'productId' => null, - 'productRequired' => false, - 'attrValue' => null, - 'note' => null, - 'expected' => [ - 'dataType' => null, - 'formElement' => null, - 'visible' => null, - 'required' => false, - 'notice' => null, - 'default' => 'required_value', - 'label' => new Phrase('mylabel'), - 'code' => 'code', - 'source' => 'product-details', - 'scopeLabel' => '', - 'globalScope' => false, - 'sortOrder' => 0 + 'default_null_prod_not_new_and_not_required' => [ + 'productId' => 1, + 'productRequired' => false, + 'attrValue' => 'val', + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => false, + 'notice' => null, + 'default' => null, + 'label' => new Phrase(null), + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0 + ], ], - ]; - } - - /** - * @return array - */ - private function defaultNullProdNewAndRequired() - { - return [ - 'productId' => null, - 'productRequired' => false, - 'attrValue' => null, - 'note' => null, - 'expected' => [ - 'dataType' => null, - 'formElement' => null, - 'visible' => null, - 'required' => false, - 'notice' => null, - 'default' => 'required_value', - 'label' => new Phrase('mylabel'), - 'code' => 'code', - 'source' => 'product-details', - 'scopeLabel' => '', - 'globalScope' => false, - 'sortOrder' => 0 - ], - ]; - } - - /** - * @return array - */ - private function defaultNullProdNewAndRequiredAndFilledNotice() - { - return [ - 'productId' => null, - 'productRequired' => false, - 'attrValue' => null, - 'note' => 'example notice', - 'expected' => [ - 'dataType' => null, - 'formElement' => null, - 'visible' => null, - 'required' => false, - 'notice' => __('example notice'), - 'default' => 'required_value', - 'label' => new Phrase('mylabel'), - 'code' => 'code', - 'source' => 'product-details', - 'scopeLabel' => '', - 'globalScope' => false, - 'sortOrder' => 0 + 'default_null_prod_new_and_not_required' => [ + 'productId' => null, + 'productRequired' => false, + 'attrValue' => null, + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => false, + 'notice' => null, + 'default' => 'required_value', + 'label' => new Phrase(null), + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0 + ], ], + 'default_null_prod_new_and_required' => [ + 'productId' => null, + 'productRequired' => false, + 'attrValue' => null, + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => false, + 'notice' => null, + 'default' => 'required_value', + 'label' => new Phrase(null), + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0 + ], + ] ]; } } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index b216ee8c9c547..0e6f17d761bc3 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -611,8 +611,9 @@ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupC // TODO: Refactor to $attribute->getOptions() when MAGETWO-48289 is done $attributeModel = $this->getAttributeModel($attribute); if ($attributeModel->usesSource()) { + $options = $attributeModel->getSource()->getAllOptions(); $meta = $this->arrayManager->merge($configPath, $meta, [ - 'options' => $attributeModel->getSource()->getAllOptions(), + 'options' => $this->convertOptionsValueToString($options), ]); } @@ -683,6 +684,23 @@ private function getAttributeDefaultValue(ProductAttributeInterface $attribute) return $attribute->getDefaultValue(); } + /** + * Convert options value to string. + * + * @param array $options + * @return array + */ + private function convertOptionsValueToString(array $options) : array + { + array_walk($options, function (&$value) { + if (isset($value['value']) && is_scalar($value['value'])) { + $value['value'] = (string)$value['value']; + } + }); + + return $options; + } + /** * @param ProductAttributeInterface $attribute * @param array $meta From 7e1e6cfbeee100984108968563bfe9d6785f9d25 Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Thu, 31 May 2018 12:16:07 +0300 Subject: [PATCH 0879/2023] MAGETWO-90370: Automate with MFTF Gift Options --- .../Checkout/Page/CheckoutCartPage.xml | 1 + .../Section/CheckoutCartProductSection.xml | 17 ++++++----- .../Checkout/Section/CheckoutCartSection.xml | 29 +++++++++++++++++++ .../Section/CheckoutCartSummarySection.xml | 4 +-- .../Section/CheckoutOrderSummarySection.xml | 5 ---- .../Section/StorefrontMiniCartSection.xml | 11 ------- .../Section/AdminOrderGiftOptionSection.xml | 16 ---------- 7 files changed, 41 insertions(+), 42 deletions(-) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSection.xml delete mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Section/AdminOrderGiftOptionSection.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Page/CheckoutCartPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Page/CheckoutCartPage.xml index 30e9bb0c95796..2e72571f15a2b 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Page/CheckoutCartPage.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Page/CheckoutCartPage.xml @@ -11,5 +11,6 @@ <page name="CheckoutCartPage" url="/checkout/cart" module="Checkout" area="storefront"> <section name="CheckoutCartProductSection"/> <section name="CheckoutCartSummarySection"/> + <section name="CheckoutCartSection"/> </page> </pages> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml index 76cdca91dd600..8364fd0e5783f 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml @@ -26,13 +26,14 @@ parameterized="true"/> <element name="RemoveItem" type="button" selector="//table[@id='shopping-cart-table']//tbody//tr[contains(@class,'item-actions')]//a[contains(@class,'action-delete')]"/> - <element name="giftOption" type="text" selector="//tr[contains(., '{{var1}}')]/following-sibling::*[contains(., '{{var2}}')]" parameterized="true"/> - <element name="giftOptionAll" type="text" selector="//div[contains(@class,'cart-gift-item')][contains(., '{{var1}}')]" parameterized="true"/> - <element name="clickGiftOptionsItem" type="button" selector=".gift-options-cart-item .action-gift"/> - <element name="clickGiftOptionsAll" type="button" selector=".gift-item-block .title span"/> - <element name="visibleSmallImageAll" type="text" selector=".gift-item-block .gift-options-content img"/> - <element name="visibleSmallImageItems" type="text" selector="#shopping-cart-table .gift-options-content img"/> - <element name="giftMessageAll" type="block" selector=".cart-gift-item .gift-message"/> - <element name="giftMessageItem" type="block" selector="#shopping-cart-table .gift-options .gift-message"/> + <element name="cartItemGiftOption" type="text" selector="//tr[contains(., '{{var1}}')]/following-sibling::*[contains(., '{{var2}}')]" parameterized="true"/> + <element name="cartGiftOptionAll" type="text" selector="//div[contains(@class,'cart-gift-item')][contains(., '{{var1}}')]" parameterized="true"/> + <element name="clickCartItemGiftOptions" type="button" selector=".gift-options-cart-item .action-gift"/> + <element name="clickCartGiftOptions" type="button" selector=".cart-gift-item div[data-role='title']"/> + <element name="cartVisibleSmallImage" type="text" selector=".gift-item-block .gift-options-content img"/> + <element name="cartItemVisibleSmallImage" type="text" selector="#shopping-cart-table .gift-options-content img"/> + <element name="cartGiftMessage" type="block" selector=".cart-gift-item .gift-message"/> + <element name="cartItemGiftMessage" type="block" selector="#shopping-cart-table .gift-options .gift-message"/> + <element name="cartItemClickButtonGiftUpdate" type="button" selector=".gift-options-cart-item button[type='submit']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSection.xml new file mode 100644 index 0000000000000..77867fb3b6d01 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSection.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> + <section name="CheckoutCartSection"> + <element name="giftWrappingName" type="text" selector=".gift-wrapping-name"/> + <element name="giftWrappingReqularPrice" type="text" selector=".gift-wrapping-title .regular-price span"/> + <element name="giftRemoveButton" type="button" selector=".gift-wrapping-title .action-remove"/> + <element name="clickImage" type="text" selector=".gift-wrapping-preview"/> + <element name="clickButtonGiftUpdate" type="button" selector=".cart-gift-item .actions-toolbar button[type='submit']"/> + <element name="giftWrapping" type="text" selector="//*[@id='cart-totals']//tr[@class='totals giftwrapping']//td[@class='amount']"/> + <element name="giftReceipt" type="text" selector=".gift-receipt label span"/> + <element name="giftReceiptCheckbox" type="checkbox" selector=".gift-receipt input"/> + <element name="giftPrintedCardCheckbox" type="checkbox" selector=".gift-printed-card input"/> + <element name="giftMessageTo" type="input" selector=".cart-gift-item .gift-message .gift-options-content .field-to input"/> + <element name="giftMessageFrom" type="input" selector=".cart-gift-item .gift-message .gift-options-content .field-from input"/> + <element name="giftMessage" type="textarea" selector=".cart-gift-item .gift-message .gift-options-content .text textarea"/> + <element name="giftWrappingNameResult" type="text" selector=".gift-summary .gift-wrapping-summary .gift-wrapping-name"/> + <element name="giftWrappingPriceResult" type="text" selector="//*[contains(., '{{var1}}')]/../span[@class='regular-price']//span[contains(., '{{var2}}')]" parameterized="true"/> + <element name="giftReceiptResult" type="text" selector=".gift-wrapping-summary span.label"/> + <element name="giftMessageResult" type="text" selector=".gift-message-summary"/> + </section> +</sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml index c63d761b5381d..c4215649c587e 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml @@ -14,7 +14,7 @@ <element name="shipping" type="text" selector="//*[@id='cart-totals']//tr[@class='totals shipping excl']//td//span[@class='price']"/> <element name="total" type="text" selector="//*[@id='cart-totals']//tr[@class='grand totals']//td//span[@class='price']"/> <element name="proceedToCheckout" type="button" selector=".action.primary.checkout span" timeout="30"/> - <element name="giftWrappingOrderPrice" type="text" selector="//tr[@class='totals giftwrapping']//td[@data-th='Gift Wrapping for Order']"/> - <element name="giftPrintedCardPrice" type="text" selector="//tr[@class='totals giftwrapping']//td[@data-th='Printed Card']"/> + <element name="giftWrappingOrderPrice" type="text" selector="#cart-totals td[data-th='Gift Wrapping for Order']"/> + <element name="giftPrintedCardPrice" type="text" selector="#cart-totals td[data-th='Printed Card']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutOrderSummarySection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutOrderSummarySection.xml index b124a2de8c151..44bd86065b808 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutOrderSummarySection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutOrderSummarySection.xml @@ -13,10 +13,5 @@ <element name="productItemName" type="text" selector=".product-item-name"/> <element name="productItemQty" type="text" selector=".value"/> <element name="productItemPrice" type="text" selector=".price"/> - <element name="giftWrappingName" type="text" selector=".gift-wrapping-name"/> - <element name="giftWrappingReqularPrice" type="text" selector=".gift-wrapping-title .regular-price span"/> - <element name="giftRemoveButton" type="button" selector=".gift-wrapping-title .action-remove"/> - <element name="clickImage" type="text" selector=".gift-wrapping-preview"/> - <element name="clickButtonGiftUpdate" type="button" selector=".gift-options .actions-toolbar button[type='submit']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/StorefrontMiniCartSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/StorefrontMiniCartSection.xml index 028e7ceef68c7..bdd97130a9715 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/StorefrontMiniCartSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/StorefrontMiniCartSection.xml @@ -23,16 +23,5 @@ <element name="viewAndEditCart" type="button" selector=".action.viewcart" timeout="30"/> <element name="miniCartItemsText" type="text" selector=".minicart-items"/> <element name="deleteMiniCartItem" type="button" selector=".action.delete" timeout="30"/> - <element name="giftWrapping" type="text" selector="//*[@id='cart-totals']//tr[@class='totals giftwrapping']//td[@class='amount']"/> - <element name="giftReceipt" type="text" selector=".gift-receipt label span"/> - <element name="giftReceiptCheckbox" type="checkbox" selector=".gift-receipt input"/> - <element name="giftPrintedCardCheckbox" type="checkbox" selector=".gift-printed-card input"/> - <element name="giftMessageTo" type="input" selector=".cart-gift-item .gift-message .gift-options-content .field-to input"/> - <element name="giftMessageFrom" type="input" selector=".cart-gift-item .gift-message .gift-options-content .field-from input"/> - <element name="giftMessage" type="textarea" selector=".cart-gift-item .gift-message .gift-options-content .text textarea"/> - <element name="giftWrappingNameResult" type="text" selector=".gift-summary .gift-wrapping-summary .gift-wrapping-name"/> - <element name="giftWrappingPriceResult" type="text" selector="//*[contains(., '{{var1}}')]/../span[@class='regular-price']//span[contains(., '{{var2}}')]" parameterized="true"/> - <element name="giftReceiptResult" type="text" selector=".gift-wrapping-summary span.label"/> - <element name="giftMessageResult" type="text" selector=".gift-message-summary span"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Section/AdminOrderGiftOptionSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Section/AdminOrderGiftOptionSection.xml deleted file mode 100644 index 946f3f132e7a6..0000000000000 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Section/AdminOrderGiftOptionSection.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - <!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - --> - -<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> - <section name="AdminOrderGiftOptionSection"> - <element name="giftOptionsImage" type="file" selector=".order-gift-options img"/> - <element name="giftWrappingDesignName" type="text" selector="//div[contains(@class, 'gift-wrapping-design')]/span"/> - <element name="giftWrappingDesignPrice" type="text" selector=".gift-wrapping-design #price-box span .price"/> - </section> -</sections> From 6cf7273f3088ba57c0604192c670407eb08d3ade Mon Sep 17 00:00:00 2001 From: Sergey <simpleadm@gmail.com> Date: Thu, 31 May 2018 12:50:47 +0300 Subject: [PATCH 0880/2023] Fixed view theme action url --- .../Theme/view/adminhtml/ui_component/design_theme_listing.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/view/adminhtml/ui_component/design_theme_listing.xml b/app/code/Magento/Theme/view/adminhtml/ui_component/design_theme_listing.xml index 204de29d54085..bb46592070c7a 100644 --- a/app/code/Magento/Theme/view/adminhtml/ui_component/design_theme_listing.xml +++ b/app/code/Magento/Theme/view/adminhtml/ui_component/design_theme_listing.xml @@ -77,7 +77,7 @@ <actionsColumn name="actions" class="Magento\Theme\Ui\Component\Listing\Column\ViewAction" sortOrder="50"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> - <item name="viewUrlPath" xsi:type="string">admin/system_design_theme/edit</item> + <item name="viewUrlPath" xsi:type="string">adminhtml/system_design_theme/edit</item> <item name="urlEntityParamName" xsi:type="string">id</item> </item> </argument> From 9a68fbd1578d30a37c6b41d48f3e0705af139c5b Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Thu, 31 May 2018 13:07:09 +0300 Subject: [PATCH 0881/2023] MAGETWO-90739: Out of stock options for configurable products still show up in search and layered navigation if Elasticsearch is enabled --- .../Api/Data/StockStatusInterface.php | 8 + .../CatalogInventory/Model/Stock/Status.php | 8 - .../Magento/Elasticsearch/Model/Config.php | 13 +- .../Plugin/DependencyUpdaterPlugin.php | 85 ++++++++ .../Plugin/StockedProductsFilterPlugin.php | 94 ++++++++ .../Plugin/DependencyUpdaterPluginTest.php | 84 ++++++++ .../StockedProductsFilterPluginTest.php | 131 +++++++++++ app/code/Magento/Elasticsearch/composer.json | 1 + app/code/Magento/Elasticsearch/etc/di.xml | 6 + .../Magento/Elasticsearch/etc/indexer.xml | 14 ++ .../Model/Client/ElasticsearchTest.php | 2 +- .../Model/Indexer/IndexHandlerTest.php | 204 ++++++++---------- .../_files/configurable_attribute.php | 63 ++++++ .../configurable_attribute_rollback.php | 29 +++ .../_files/configurable_products.php | 4 +- .../_files/configurable_products_rollback.php | 2 +- .../Magento/Elasticsearch/_files/indexer.php | 8 +- .../Magento/Elasticsearch/_files/requests.xml | 5 + .../Search/Adapter/Mysql/AdapterTest.php | 11 + .../Search/_files/product_configurable.php | 2 - .../Framework/Search/_files/requests.xml | 5 + .../Search/_files/search_weight_products.php | 10 - 22 files changed, 645 insertions(+), 144 deletions(-) create mode 100644 app/code/Magento/Elasticsearch/Model/Indexer/Plugin/DependencyUpdaterPlugin.php create mode 100644 app/code/Magento/Elasticsearch/Model/Indexer/Plugin/StockedProductsFilterPlugin.php create mode 100644 app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/DependencyUpdaterPluginTest.php create mode 100644 app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php create mode 100644 app/code/Magento/Elasticsearch/etc/indexer.xml create mode 100644 dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute.php create mode 100644 dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute_rollback.php diff --git a/app/code/Magento/CatalogInventory/Api/Data/StockStatusInterface.php b/app/code/Magento/CatalogInventory/Api/Data/StockStatusInterface.php index 83defa64df250..c9ae6a96a3671 100644 --- a/app/code/Magento/CatalogInventory/Api/Data/StockStatusInterface.php +++ b/app/code/Magento/CatalogInventory/Api/Data/StockStatusInterface.php @@ -14,6 +14,14 @@ */ interface StockStatusInterface extends ExtensibleDataInterface { + /**#@+ + * Stock Status values. + */ + const STATUS_OUT_OF_STOCK = 0; + + const STATUS_IN_STOCK = 1; + /**#@-*/ + /**#@+ * Stock status object data keys */ diff --git a/app/code/Magento/CatalogInventory/Model/Stock/Status.php b/app/code/Magento/CatalogInventory/Model/Stock/Status.php index 9a56c8e8804ec..899056d8f0835 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/Status.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/Status.php @@ -17,14 +17,6 @@ */ class Status extends AbstractExtensibleModel implements StockStatusInterface { - /**#@+ - * Stock Status values - */ - const STATUS_OUT_OF_STOCK = 0; - - const STATUS_IN_STOCK = 1; - /**#@-*/ - /**#@+ * Field name */ diff --git a/app/code/Magento/Elasticsearch/Model/Config.php b/app/code/Magento/Elasticsearch/Model/Config.php index 93e715f928047..6f4e54e96fb9b 100644 --- a/app/code/Magento/Elasticsearch/Model/Config.php +++ b/app/code/Magento/Elasticsearch/Model/Config.php @@ -6,6 +6,7 @@ namespace Magento\Elasticsearch\Model; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Search\Model\EngineResolver; use Magento\Store\Model\ScopeInterface; use Magento\AdvancedSearch\Model\Client\ClientOptionsInterface; use Magento\AdvancedSearch\Model\Client\ClientResolver; @@ -58,17 +59,19 @@ class Config implements ClientOptionsInterface * Constructor * * @param ScopeConfigInterface $scopeConfig - * @param ClientResolver $clientResolver - * @param string $prefix + * @param ClientResolver|null $clientResolver + * @param EngineResolver|null $engineResolver + * @param string|null $prefix */ public function __construct( ScopeConfigInterface $scopeConfig, ClientResolver $clientResolver = null, + EngineResolver $engineResolver = null, $prefix = null ) { $this->scopeConfig = $scopeConfig; - $this->clientResolver = $clientResolver ?: - ObjectManager::getInstance()->get(ClientResolver::class); + $this->clientResolver = $clientResolver ?: ObjectManager::getInstance()->get(ClientResolver::class); + $this->engineResolver = $engineResolver ?: ObjectManager::getInstance()->get(EngineResolver::class); $this->prefix = $prefix ?: $this->clientResolver->getCurrentEngine(); } @@ -126,7 +129,7 @@ public function getSearchConfigData($field, $storeId = null) */ public function isElasticsearchEnabled() { - return $this->getSearchConfigData('engine') == self::ENGINE_NAME; + return $this->engineResolver->getCurrentSearchEngine() === self::ENGINE_NAME; } /** diff --git a/app/code/Magento/Elasticsearch/Model/Indexer/Plugin/DependencyUpdaterPlugin.php b/app/code/Magento/Elasticsearch/Model/Indexer/Plugin/DependencyUpdaterPlugin.php new file mode 100644 index 0000000000000..f1b153c98b2af --- /dev/null +++ b/app/code/Magento/Elasticsearch/Model/Indexer/Plugin/DependencyUpdaterPlugin.php @@ -0,0 +1,85 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Elasticsearch\Model\Indexer\Plugin; + +use Magento\Elasticsearch\Model\Config; +use Magento\Framework\Indexer\Config\DependencyInfoProvider as Provider; +use Magento\CatalogSearch\Model\Indexer\Fulltext as CatalogSearchFulltextIndexer; +use Magento\CatalogInventory\Model\Indexer\Stock\Processor as CatalogInventoryStockIndexer; + +/** + * Plugin for maintenance catalog search index dependency on stock index. + * If elasticsearch is used as search engine catalog search index becomes dependent on stock index. Elasticsearch + * module declares this dependence. But in case when elasticsearch module is enabled and elasticsearch engine isn`t + * used as search engine other search engines don`t need this dependency. + * This plugin remove catalog search index dependency on stock index when elasticsearch isn`t used as search engine + * except full reindexing. During full reindexing this dependency doesn`t make overhead. + */ +class DependencyUpdaterPlugin +{ + /** + * @var Config + */ + private $config; + + /** + * @param Config $config + */ + public function __construct(Config $config) + { + $this->config = $config; + } + + /** + * Remove index dependency, if it needed, on run reindexing by specifics indexes. + * + * @param Provider $provider + * @param array $dependencies + * @param string $indexerId + * @return array + * @see \Magento\Indexer\Console\Command\IndexerReindexCommand::getIndexers() + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetIndexerIdsToRunBefore(Provider $provider, array $dependencies, string $indexerId): array + { + if ($this->isFilteringNeeded($indexerId, CatalogSearchFulltextIndexer::INDEXER_ID)) { + $dependencies = array_diff($dependencies, [CatalogInventoryStockIndexer::INDEXER_ID]); + } + + return $dependencies; + } + + /** + * Remove index dependency, if it needed, on reindex triggers. + * + * @param Provider $provider + * @param array $dependencies + * @param string $indexerId + * @return array + * @see \Magento\Indexer\Model\Indexer\DependencyDecorator + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetIndexerIdsToRunAfter(Provider $provider, array $dependencies, string $indexerId): array + { + if ($this->isFilteringNeeded($indexerId, CatalogInventoryStockIndexer::INDEXER_ID)) { + $dependencies = array_diff($dependencies, [CatalogSearchFulltextIndexer::INDEXER_ID]); + } + + return $dependencies; + } + + /** + * @param string $currentIndexerId + * @param string $targetIndexerId + * @return bool + */ + private function isFilteringNeeded(string $currentIndexerId, string $targetIndexerId): bool + { + return (!$this->config->isElasticsearchEnabled() && $targetIndexerId === $currentIndexerId); + } +} diff --git a/app/code/Magento/Elasticsearch/Model/Indexer/Plugin/StockedProductsFilterPlugin.php b/app/code/Magento/Elasticsearch/Model/Indexer/Plugin/StockedProductsFilterPlugin.php new file mode 100644 index 0000000000000..ec18b955a2917 --- /dev/null +++ b/app/code/Magento/Elasticsearch/Model/Indexer/Plugin/StockedProductsFilterPlugin.php @@ -0,0 +1,94 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Elasticsearch\Model\Indexer\Plugin; + +use Magento\Elasticsearch\Model\Config; +use Magento\CatalogInventory\Api\StockConfigurationInterface; +use Magento\CatalogInventory\Api\StockStatusRepositoryInterface; +use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory; +use Magento\CatalogInventory\Api\Data\StockStatusInterface; +use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\DataProvider; + +/** + * Plugin for filtering child products that are out of stock for preventing their saving to catalog search index. + */ +class StockedProductsFilterPlugin +{ + /** + * @var Config + */ + private $config; + + /** + * @var StockConfigurationInterface + */ + private $stockConfiguration; + + /** + * @var StockStatusRepositoryInterface + */ + private $stockStatusRepository; + + /** + * @var StockStatusCriteriaInterfaceFactory + */ + private $stockStatusCriteriaFactory; + + /** + * @param Config $config + * @param StockConfigurationInterface $stockConfiguration + * @param StockStatusRepositoryInterface $stockStatusRepository + * @param StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory + */ + public function __construct( + Config $config, + StockConfigurationInterface $stockConfiguration, + StockStatusRepositoryInterface $stockStatusRepository, + StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory + ) { + $this->config = $config; + $this->stockConfiguration = $stockConfiguration; + $this->stockStatusRepository = $stockStatusRepository; + $this->stockStatusCriteriaFactory = $stockStatusCriteriaFactory; + } + + /** + * Filter out of stock options for configurable product. + * + * @param DataProvider $dataProvider + * @param array $indexData + * @param array $productData + * @param int $storeId + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforePrepareProductIndex( + DataProvider $dataProvider, + array $indexData, + array $productData, + int $storeId + ): array { + if ($this->config->isElasticsearchEnabled() && !$this->stockConfiguration->isShowOutOfStock($storeId)) { + $productIds = array_keys($indexData); + $stockStatusCriteria = $this->stockStatusCriteriaFactory->create(); + $stockStatusCriteria->setProductsFilter($productIds); + $stockStatusCollection = $this->stockStatusRepository->getList($stockStatusCriteria); + $stockStatuses = $stockStatusCollection->getItems(); + $stockStatuses = array_filter($stockStatuses, function (StockStatusInterface $stockStatus) { + return StockStatusInterface::STATUS_IN_STOCK == $stockStatus->getStockStatus(); + }); + $indexData = array_intersect_key($indexData, $stockStatuses); + } + + return [ + $indexData, + $productData, + $storeId, + ]; + } +} diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/DependencyUpdaterPluginTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/DependencyUpdaterPluginTest.php new file mode 100644 index 0000000000000..9b43d7d40ab1a --- /dev/null +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/DependencyUpdaterPluginTest.php @@ -0,0 +1,84 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Elasticsearch\Test\Unit\Model\Indexer\Plugin; + +use Magento\Elasticsearch\Model\Config; +use Magento\Elasticsearch\Model\Indexer\Plugin\DependencyUpdaterPlugin; +use Magento\Framework\Indexer\Config\DependencyInfoProvider; +use Magento\CatalogSearch\Model\Indexer\Fulltext as CatalogSearchFulltextIndexer; +use Magento\CatalogInventory\Model\Indexer\Stock\Processor as CatalogInventoryStockIndexer; + +/** + * Test for Magento\Elasticsearch\Model\Indexer\Plugin\DependencyUpdaterPlugin class. + */ +class DependencyUpdaterPluginTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $configMock; + + /** + * @var DependencyUpdaterPlugin + */ + private $plugin; + + /** + * @var DependencyInfoProvider|\PHPUnit_Framework_MockObject_MockObject + */ + private $providerMock; + + protected function setUp() + { + $this->configMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + $this->configMock->expects($this->exactly(2)) + ->method('isElasticsearchEnabled') + ->willReturnOnConsecutiveCalls(true, false); + $this->providerMock = $this->getMockBuilder(DependencyInfoProvider::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->plugin = new DependencyUpdaterPlugin($this->configMock); + } + + /** + * @return void + */ + public function testAfterGetIndexerIdsToRunBefore(): void + { + $dependencies = [ + CatalogInventoryStockIndexer::INDEXER_ID, + ]; + $indexerId = CatalogSearchFulltextIndexer::INDEXER_ID; + + $indexerIds = $this->plugin->afterGetIndexerIdsToRunBefore($this->providerMock, $dependencies, $indexerId); + $this->assertContains(CatalogInventoryStockIndexer::INDEXER_ID, $indexerIds); + + $indexerIds = $this->plugin->afterGetIndexerIdsToRunBefore($this->providerMock, $dependencies, $indexerId); + $this->assertNotContains(CatalogInventoryStockIndexer::INDEXER_ID, $indexerIds); + } + + /** + * @return void + */ + public function testAfterGetIndexerIdsToRunAfter(): void + { + $dependencies = [ + CatalogSearchFulltextIndexer::INDEXER_ID, + ]; + $indexerId = CatalogInventoryStockIndexer::INDEXER_ID; + + $indexerIds = $this->plugin->afterGetIndexerIdsToRunAfter($this->providerMock, $dependencies, $indexerId); + $this->assertContains(CatalogSearchFulltextIndexer::INDEXER_ID, $indexerIds); + + $indexerIds = $this->plugin->afterGetIndexerIdsToRunAfter($this->providerMock, $dependencies, $indexerId); + $this->assertNotContains(CatalogSearchFulltextIndexer::INDEXER_ID, $indexerIds); + } +} diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php new file mode 100644 index 0000000000000..dc4a92016d1fb --- /dev/null +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php @@ -0,0 +1,131 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Elasticsearch\Test\Unit\Model\Indexer\Plugin; + +use Magento\Elasticsearch\Model\Config; +use Magento\Elasticsearch\Model\Indexer\Plugin\StockedProductsFilterPlugin; +use Magento\CatalogInventory\Api\StockConfigurationInterface; +use Magento\CatalogInventory\Api\StockStatusRepositoryInterface; +use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory; +use Magento\CatalogInventory\Api\StockStatusCriteriaInterface; +use Magento\CatalogInventory\Api\Data\StockStatusCollectionInterface; +use Magento\CatalogInventory\Api\Data\StockStatusInterface; +use Magento\CatalogInventory\Model\Stock; +use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\DataProvider; + +/** + * Test for Magento\Elasticsearch\Model\Indexer\Plugin\StockedProductsFilterPlugin class. + */ +class StockedProductsFilterPluginTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $configMock; + + /** + * @var StockConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $stockConfigurationMock; + + /** + * @var StockStatusRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $stockStatusRepositoryMock; + + /** + * @var StockStatusCriteriaInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $stockStatusCriteriaFactoryMock; + + /** + * @var StockedProductsFilterPlugin + */ + private $plugin; + + protected function setUp() + { + $this->configMock = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock(); + $this->stockConfigurationMock = $this->getMockBuilder(StockConfigurationInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->stockStatusRepositoryMock = $this->getMockBuilder(StockStatusRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->stockStatusCriteriaFactoryMock = $this->getMockBuilder(StockStatusCriteriaInterfaceFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->plugin = new StockedProductsFilterPlugin( + $this->configMock, + $this->stockConfigurationMock, + $this->stockStatusRepositoryMock, + $this->stockStatusCriteriaFactoryMock + ); + } + + /** + * @return void + */ + public function testBeforePrepareProductIndex(): void + { + /** @var DataProvider|\PHPUnit_Framework_MockObject_MockObject $dataProviderMock */ + $dataProviderMock = $this->getMockBuilder(DataProvider::class)->disableOriginalConstructor()->getMock(); + $indexData = [ + 1 => [], + 2 => [], + ]; + $productData = []; + $storeId = 1; + + $this->configMock + ->expects($this->once()) + ->method('isElasticsearchEnabled') + ->willReturn(true); + $this->stockConfigurationMock + ->expects($this->once()) + ->method('isShowOutOfStock') + ->willReturn(false); + + $stockStatusCriteriaMock = $this->getMockBuilder(StockStatusCriteriaInterface::class)->getMock(); + $stockStatusCriteriaMock + ->expects($this->once()) + ->method('setProductsFilter') + ->willReturn(true); + $this->stockStatusCriteriaFactoryMock + ->expects($this->once()) + ->method('create') + ->willReturn($stockStatusCriteriaMock); + + $stockStatusMock = $this->getMockBuilder(StockStatusInterface::class)->getMock(); + $stockStatusMock->expects($this->atLeastOnce()) + ->method('getStockStatus') + ->willReturnOnConsecutiveCalls(Stock::STOCK_IN_STOCK, Stock::STOCK_OUT_OF_STOCK); + $stockStatusCollectionMock = $this->getMockBuilder(StockStatusCollectionInterface::class)->getMock(); + $stockStatusCollectionMock + ->expects($this->once()) + ->method('getItems') + ->willReturn([ + 1 => $stockStatusMock, + 2 => $stockStatusMock, + ]); + $this->stockStatusRepositoryMock + ->expects($this->once()) + ->method('getList') + ->willReturn($stockStatusCollectionMock); + + list ($indexData, $productData, $storeId) = $this->plugin->beforePrepareProductIndex( + $dataProviderMock, + $indexData, + $productData, + $storeId + ); + + $this->assertEquals([1], array_keys($indexData)); + } +} diff --git a/app/code/Magento/Elasticsearch/composer.json b/app/code/Magento/Elasticsearch/composer.json index 8e379579641d3..a6b4f93ade579 100644 --- a/app/code/Magento/Elasticsearch/composer.json +++ b/app/code/Magento/Elasticsearch/composer.json @@ -10,6 +10,7 @@ "magento/module-eav": "*", "magento/module-search": "*", "magento/module-store": "*", + "magento/module-catalog-inventory": "*", "magento/framework": "*", "elasticsearch/elasticsearch": "~2.0|~5.1" }, diff --git a/app/code/Magento/Elasticsearch/etc/di.xml b/app/code/Magento/Elasticsearch/etc/di.xml index b3ba240ae239c..2d569eecfee58 100644 --- a/app/code/Magento/Elasticsearch/etc/di.xml +++ b/app/code/Magento/Elasticsearch/etc/di.xml @@ -189,6 +189,12 @@ </argument> </arguments> </type> + <type name="Magento\CatalogSearch\Model\Indexer\Fulltext\Action\DataProvider"> + <plugin name="stockedProductsFilterPlugin" type="Magento\Elasticsearch\Model\Indexer\Plugin\StockedProductsFilterPlugin"/> + </type> + <type name="Magento\Framework\Indexer\Config\DependencyInfoProvider"> + <plugin name="indexerDependencyUpdaterPlugin" type="Magento\Elasticsearch\Model\Indexer\Plugin\DependencyUpdaterPlugin"/> + </type> <type name="Magento\Elasticsearch\SearchAdapter\Query\Builder\Match"> <arguments> <argument name="preprocessorContainer" xsi:type="array"> diff --git a/app/code/Magento/Elasticsearch/etc/indexer.xml b/app/code/Magento/Elasticsearch/etc/indexer.xml new file mode 100644 index 0000000000000..245829396a67b --- /dev/null +++ b/app/code/Magento/Elasticsearch/etc/indexer.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Indexer/etc/indexer.xsd"> + <indexer id="catalogsearch_fulltext"> + <dependencies> + <indexer id="cataloginventory_stock" /> + </dependencies> + </indexer> +</config> diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Client/ElasticsearchTest.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Client/ElasticsearchTest.php index 0731871b4bd40..61add5f7d0ea7 100644 --- a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Client/ElasticsearchTest.php +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Client/ElasticsearchTest.php @@ -100,7 +100,7 @@ private function search($text) */ public function testSearchConfigurableProductBySimpleProductName() { - $this->assertProductWithSkuFound('configurable', $this->search('Configurable OptionOption')); + $this->assertProductWithSkuFound('configurable', $this->search('Configurable Option')); } /** diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php index 4cdff533af737..36d3c809242fc 100755 --- a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php @@ -5,13 +5,18 @@ */ namespace Magento\Elasticsearch\Model\Indexer; -use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Action as ProductAction; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\CatalogInventory\Api\StockRegistryInterface; +use Magento\CatalogInventory\Api\StockItemRepositoryInterface; +use Magento\CatalogSearch\Model\Indexer\Fulltext as CatalogSearchFulltextIndexer; use Magento\TestFramework\Helper\Bootstrap; use Magento\Store\Model\StoreManagerInterface; use Magento\Elasticsearch\SearchAdapter\ConnectionManager; use Magento\Elasticsearch\Model\Client\Elasticsearch as ElasticsearchClient; use Magento\Elasticsearch\Model\Config; use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver; +use Magento\Indexer\Model\Indexer; /** * Important: Please make sure that each integration test file works with unique elastic search index. In order to @@ -20,107 +25,79 @@ * * @magentoDbIsolation disabled * @magentoDataFixture Magento/Elasticsearch/_files/indexer.php + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class IndexHandlerTest extends \PHPUnit\Framework\TestCase { /** - * @var ConnectionManager + * @var ProductRepositoryInterface */ - protected $connectionManager; + private $productRepository; /** * @var ElasticsearchClient */ - protected $client; + private $client; /** * @var StoreManagerInterface */ - protected $storeManager; + private $storeManager; /** * @var int[] */ - protected $storeIds; + private $storeIds; /** - * @var Config + * @var string */ - protected $clientConfig; + private $entityType; /** - * @var SearchIndexNameResolver - */ - protected $searchIndexNameResolver; - - /** - * @var Product - */ - protected $productApple; - - /** - * @var Product - */ - protected $productBanana; - - /** - * @var Product - */ - protected $productOrange; - - /** - * @var Product + * @var Indexer */ - protected $productPapaya; + private $indexer; /** - * @var Product + * @var SearchIndexNameResolver */ - protected $productCherry; + private $searchIndexNameResolver; /** - * Setup method + * {@inheritdoc} */ protected function setUp() { - $this->connectionManager = Bootstrap::getObjectManager()->create( - \Magento\Elasticsearch\SearchAdapter\ConnectionManager::class - ); - - $this->client = $this->connectionManager->getConnection(); + $connectionManager = Bootstrap::getObjectManager()->create(ConnectionManager::class); + $this->client = $connectionManager->getConnection(); - $this->storeManager = Bootstrap::getObjectManager()->create( - \Magento\Store\Model\StoreManagerInterface::class - ); + $this->storeManager = Bootstrap::getObjectManager()->create(StoreManagerInterface::class); $this->storeIds = array_keys($this->storeManager->getStores()); - $this->clientConfig = Bootstrap::getObjectManager()->create( - \Magento\Elasticsearch\Model\Config::class - ); + $clientConfig = Bootstrap::getObjectManager()->create(Config::class); + $this->entityType = $clientConfig->getEntityType(); - $this->searchIndexNameResolver = Bootstrap::getObjectManager()->create( - \Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver::class - ); + $this->indexer = Bootstrap::getObjectManager()->create(Indexer::class); + $this->indexer->load(CatalogSearchFulltextIndexer::INDEXER_ID); + $this->indexer->reindexAll(); - $this->productApple = $this->getProductBySku('fulltext-1'); - $this->productBanana = $this->getProductBySku('fulltext-2'); - $this->productOrange = $this->getProductBySku('fulltext-3'); - $this->productPapaya = $this->getProductBySku('fulltext-4'); - $this->productCherry = $this->getProductBySku('fulltext-5'); + $this->searchIndexNameResolver = Bootstrap::getObjectManager()->create(SearchIndexNameResolver::class); + $this->productRepository = Bootstrap::getObjectManager()->create(ProductRepositoryInterface::class); } /** - * Test reindex process * @magentoConfigFixture default/catalog/search/engine elasticsearch * @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest + * @return void */ - public function testReindexAll() + public function testReindexAll(): void { - $this->reindexAll(); + $productApple = $this->productRepository->get('fulltext-1'); foreach ($this->storeIds as $storeId) { $products = $this->searchByName('Apple', $storeId); $this->assertCount(1, $products); - $this->assertEquals($this->productApple->getId(), $products[0]['_id']); + $this->assertEquals($productApple->getId(), $products[0]['_id']); $products = $this->searchByName('Simple Product', $storeId); $this->assertCount(5, $products); @@ -128,19 +105,17 @@ public function testReindexAll() } /** + * @magentoAppIsolation enabled * @magentoConfigFixture default/catalog/search/engine elasticsearch * @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest + * @return void */ - public function testReindexRowAfterEdit() + public function testReindexRowAfterEdit(): void { - // The test executes fine locally. On bamboo there is some issue with parallel test execution or other - // test interaction. It is being marked as skipped until more time is available to investigate and - // fix the issue. - $this->markTestSkipped('MAGETWO-53851 - Ticket to investiage this test failure on Bamboo and fix it.'); - - $this->productApple->setData('name', 'Simple Product Cucumber'); - $this->productApple->save(); - $this->reindexAll(); + $this->storeManager->setCurrentStore('admin'); + $productApple = $this->productRepository->get('fulltext-1'); + $productApple->setName('Simple Product Cucumber'); + $this->productRepository->save($productApple); foreach ($this->storeIds as $storeId) { $products = $this->searchByName('Apple', $storeId); @@ -148,7 +123,7 @@ public function testReindexRowAfterEdit() $products = $this->searchByName('Cucumber', $storeId); $this->assertCount(1, $products); - $this->assertEquals($this->productApple->getId(), $products[0]['_id']); + $this->assertEquals($productApple->getId(), $products[0]['_id']); $products = $this->searchByName('Simple Product', $storeId); $this->assertCount(5, $products); @@ -158,22 +133,21 @@ public function testReindexRowAfterEdit() /** * @magentoConfigFixture default/catalog/search/engine elasticsearch * @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest + * @return void */ - public function testReindexRowAfterMassAction() + public function testReindexRowAfterMassAction(): void { - $this->reindexAll(); + $productApple = $this->productRepository->get('fulltext-1'); + $productBanana = $this->productRepository->get('fulltext-2'); $productIds = [ - $this->productApple->getId(), - $this->productBanana->getId(), + $productApple->getId(), + $productBanana->getId(), ]; $attrData = [ 'name' => 'Simple Product Common', ]; - - /** @var \Magento\Catalog\Model\Product\Action $action */ - $action = Bootstrap::getObjectManager()->get( - \Magento\Catalog\Model\Product\Action::class - ); + /** @var ProductAction $action */ + $action = Bootstrap::getObjectManager()->get(ProductAction::class); foreach ($this->storeIds as $storeId) { $action->updateAttributes($productIds, $attrData, $storeId); @@ -199,30 +173,66 @@ public function testReindexRowAfterMassAction() * @magentoConfigFixture default/catalog/search/engine elasticsearch * @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest * @magentoAppArea adminhtml + * @return void */ - public function testReindexRowAfterDelete() + public function testReindexRowAfterDelete(): void { - $this->reindexAll(); - $this->productBanana->delete(); + $productBanana = $this->productRepository->get('fulltext-2'); + $this->productRepository->delete($productBanana); foreach ($this->storeIds as $storeId) { + $products = $this->searchByName('Banana', $storeId); + $this->assertEmpty($products); + $products = $this->searchByName('Simple Product', $storeId); $this->assertCount(4, $products); } } /** - * Search docs in Elasticsearch by name + * @magentoAppArea adminhtml + * @magentoConfigFixture default/catalog/search/engine elasticsearch + * @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest + * @magentoDataFixture Magento/Elasticsearch/_files/configurable_products.php + * @return void + */ + public function testReindexRowAfterUpdateStockStatus(): void + { + foreach ($this->storeIds as $storeId) { + $products = $this->searchByName('ProductOption1', $storeId); + $this->assertNotEmpty($products); + } + $product = $this->productRepository->get('simple_10'); + /** @var StockRegistryInterface $stockRegistry */ + $stockRegistry = Bootstrap::getObjectManager()->create(StockRegistryInterface::class); + $stockItem = $stockRegistry->getStockItem($product->getId()); + $stockItem->setIsInStock(false); + /** @var StockItemRepositoryInterface $stockRepository */ + $stockRepository = Bootstrap::getObjectManager()->create(StockItemRepositoryInterface::class); + $stockRepository->save($stockItem); + + foreach ($this->storeIds as $storeId) { + $products = $this->searchByName('ProductOption1', $storeId); + $this->assertEmpty($products); + + $products = $this->searchByName('Configurable', $storeId); + $this->assertNotEmpty($products); + } + } + + /** + * Search docs in Elasticsearch by name. * * @param string $text * @param int $storeId * @return array */ - protected function searchByName($text, $storeId) + private function searchByName(string $text, int $storeId): array { + $index = $this->searchIndexNameResolver->getIndexName($storeId, $this->indexer->getId()); $searchQuery = [ - 'index' => $this->searchIndexNameResolver->getIndexName($storeId, 'catalogsearch_fulltext'), - 'type' => $this->clientConfig->getEntityType(), + 'index' => $index, + 'type' => $this->entityType, 'body' => [ 'query' => [ 'bool' => [ @@ -240,35 +250,7 @@ protected function searchByName($text, $storeId) ]; $queryResult = $this->client->query($searchQuery); $products = isset($queryResult['hits']['hits']) ? $queryResult['hits']['hits'] : []; - return $products; - } - - /** - * Return product by SKU - * - * @param string $sku - * @return Product - */ - protected function getProductBySku($sku) - { - /** @var Product $product */ - $product = Bootstrap::getObjectManager()->get( - \Magento\Catalog\Model\Product::class - ); - return $product->loadByAttribute('sku', $sku); - } - /** - * Perform full reindex - * - * @return void - */ - private function reindexAll() - { - $indexer = Bootstrap::getObjectManager()->create( - \Magento\Indexer\Model\Indexer::class - ); - $indexer->load('catalogsearch_fulltext'); - $indexer->reindexAll(); + return $products; } } diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute.php new file mode 100644 index 0000000000000..66d4d467bf6f4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Eav\Api\AttributeRepositoryInterface; + +$eavConfig = Bootstrap::getObjectManager()->get(\Magento\Eav\Model\Config::class); +$attribute = $eavConfig->getAttribute('catalog_product', 'test_configurable'); + +$eavConfig->clear(); + +/** @var $installer \Magento\Catalog\Setup\CategorySetup */ +$installer = Bootstrap::getObjectManager()->create(\Magento\Catalog\Setup\CategorySetup::class); + +if (!$attribute->getId()) { + + /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ + $attribute = Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class + ); + + /** @var AttributeRepositoryInterface $attributeRepository */ + $attributeRepository = Bootstrap::getObjectManager()->create(AttributeRepositoryInterface::class); + + $attribute->setData( + [ + 'attribute_code' => 'test_configurable', + 'entity_type_id' => $installer->getEntityTypeId('catalog_product'), + 'is_global' => 1, + 'is_user_defined' => 1, + 'frontend_input' => 'select', + 'is_unique' => 0, + 'is_required' => 0, + 'is_searchable' => 0, + 'is_visible_in_advanced_search' => 0, + 'is_comparable' => 0, + 'is_filterable' => 0, + 'is_filterable_in_search' => 0, + 'is_used_for_promo_rules' => 0, + 'is_html_allowed_on_front' => 1, + 'is_visible_on_front' => 0, + 'used_in_product_listing' => 0, + 'used_for_sort_by' => 0, + 'frontend_label' => ['Test Configurable'], + 'backend_type' => 'int', + 'option' => [ + 'value' => ['option_0' => ['Option 1'], 'option_1' => ['Option 2']], + 'order' => ['option_0' => 1, 'option_1' => 2], + ], + ] + ); + + $attributeRepository->save($attribute); + + /* Assign attribute to attribute set */ + $installer->addAttributeToGroup('catalog_product', 'Default', 'General', $attribute->getId()); +} + +$eavConfig->clear(); diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute_rollback.php new file mode 100644 index 0000000000000..f302df996f902 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute_rollback.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +/** @var \Magento\Framework\Registry $registry */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +$productCollection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Catalog\Model\ResourceModel\Product\Collection::class); +foreach ($productCollection as $product) { + $product->delete(); +} + +$eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Eav\Model\Config::class); +$attribute = $eavConfig->getAttribute('catalog_product', 'test_configurable'); +if ($attribute instanceof \Magento\Eav\Model\Entity\Attribute\AbstractAttribute + && $attribute->getId() +) { + $attribute->delete(); +} +$eavConfig->clear(); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_products.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_products.php index c2dd3c2f879e1..f8872b02ba246 100644 --- a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_products.php +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_products.php @@ -17,7 +17,7 @@ require __DIR__ . '/select_attribute.php'; require __DIR__ . '/multiselect_attribute.php'; -require __DIR__ . '/../../ConfigurableProduct/_files/configurable_attribute.php'; +require __DIR__ . '/configurable_attribute.php'; $objectManager = Bootstrap::getObjectManager(); @@ -45,7 +45,7 @@ ->setId($productId) ->setAttributeSetId($attributeSetId) ->setWebsiteIds([1]) - ->setName('Configurable Option' . $option->getLabel()) + ->setName('Configurable Option Product' . str_replace(' ', '', $option->getLabel())) ->setSku('simple_' . $productId) ->setPrice($productId) ->setTestConfigurable($option->getValue()) diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_products_rollback.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_products_rollback.php index 0d062c9d3f4e4..e73d2ab1b5906 100644 --- a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_products_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_products_rollback.php @@ -25,7 +25,7 @@ } } -require __DIR__ . '/../../ConfigurableProduct/_files/configurable_attribute_rollback.php'; +require __DIR__ . '/configurable_attribute_rollback.php'; require __DIR__ . '/select_attribute_rollback.php'; require __DIR__ . '/multiselect_attribute_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/indexer.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/indexer.php index 8ee3a40915028..b5c86a63fa47f 100644 --- a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/indexer.php +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/indexer.php @@ -52,7 +52,7 @@ ->setStockData(['use_config_manage_stock' => 0]) ->save(); -/** @var $productFirst \Magento\Catalog\Model\Product */ +/** @var $productSecond \Magento\Catalog\Model\Product */ $productSecond = $objectManager->create(\Magento\Catalog\Model\Product::class); $productSecond->setTypeId('simple') ->setAttributeSetId(4) @@ -68,7 +68,7 @@ ->setStockData(['use_config_manage_stock' => 0]) ->save(); -/** @var $productFirst \Magento\Catalog\Model\Product */ +/** @var $productThird \Magento\Catalog\Model\Product */ $productThird = $objectManager->create(\Magento\Catalog\Model\Product::class); $productThird->setTypeId('simple') ->setAttributeSetId(4) @@ -84,7 +84,7 @@ ->setStockData(['use_config_manage_stock' => 0]) ->save(); -/** @var $productFirst \Magento\Catalog\Model\Product */ +/** @var $productFourth \Magento\Catalog\Model\Product */ $productFourth = $objectManager->create(\Magento\Catalog\Model\Product::class); $productFourth->setTypeId('simple') ->setAttributeSetId(4) @@ -100,7 +100,7 @@ ->setStockData(['use_config_manage_stock' => 0]) ->save(); -/** @var $productFirst \Magento\Catalog\Model\Product */ +/** @var $productFifth \Magento\Catalog\Model\Product */ $productFifth = $objectManager->create(\Magento\Catalog\Model\Product::class); $productFifth->setTypeId('simple') ->setAttributeSetId(4) diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/requests.xml b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/requests.xml index c40ac9e8b9b1c..0aaaf9b85857f 100644 --- a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/requests.xml +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/requests.xml @@ -394,13 +394,18 @@ <queries> <query xsi:type="boolQuery" name="filter_out_of_stock_child" boost="1"> <queryReference clause="must" ref="test_configurable"/> + <queryReference clause="must" ref="visibility"/> </query> <query xsi:type="filteredQuery" name="test_configurable"> <filterReference clause="must" ref="test_configurable_filter"/> </query> + <query xsi:type="filteredQuery" name="visibility"> + <filterReference clause="must" ref="visibility_filter"/> + </query> </queries> <filters> <filter xsi:type="termFilter" name="test_configurable_filter" field="test_configurable" value="$test_configurable$"/> + <filter xsi:type="termFilter" name="visibility_filter" field="visibility" value="$visibility$"/> </filters> <aggregations/> <from>0</from> diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php index ec1538e950c12..73d330e5dc491 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php @@ -63,6 +63,10 @@ protected function setUp() ); $this->adapter = $this->createAdapter(); + + $indexer = $this->objectManager->create(\Magento\Indexer\Model\Indexer::class); + $indexer->load('catalogsearch_fulltext'); + $indexer->reindexAll(); } /** @@ -531,9 +535,15 @@ public function testAdvancedSearchCompositeProductWithOutOfStockOption() ->create(Collection::class) ->setAttributeFilter($attribute->getId()); + $visibility = [ + \Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_SEARCH, + \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH, + ]; + $firstOption = $selectOptions->getFirstItem(); $firstOptionId = $firstOption->getId(); $this->requestBuilder->bind('test_configurable', $firstOptionId); + $this->requestBuilder->bind('visibility', $visibility); $this->requestBuilder->setRequestName('filter_out_of_stock_child'); $queryResponse = $this->executeQuery(); @@ -542,6 +552,7 @@ public function testAdvancedSearchCompositeProductWithOutOfStockOption() $secondOption = $selectOptions->getLastItem(); $secondOptionId = $secondOption->getId(); $this->requestBuilder->bind('test_configurable', $secondOptionId); + $this->requestBuilder->bind('visibility', $visibility); $this->requestBuilder->setRequestName('filter_out_of_stock_child'); $queryResponse = $this->executeQuery(); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php index 2f30cba3d8ee6..8a7c5246f373a 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php @@ -15,8 +15,6 @@ use Magento\Eav\Api\Data\AttributeOptionInterface; use Magento\TestFramework\Helper\Bootstrap; -Bootstrap::getInstance()->reinitialize(); - require __DIR__ . '/configurable_attribute.php'; /** @var ProductRepositoryInterface $productRepository */ diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml index 70f9ac75b07f3..dcf3cd582507c 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/requests.xml @@ -394,13 +394,18 @@ <queries> <query xsi:type="boolQuery" name="filter_out_of_stock_child" boost="1"> <queryReference clause="must" ref="test_configurable"/> + <queryReference clause="must" ref="visibility"/> </query> <query xsi:type="filteredQuery" name="test_configurable"> <filterReference clause="must" ref="test_configurable_filter"/> </query> + <query xsi:type="filteredQuery" name="visibility"> + <filterReference clause="must" ref="visibility_filter"/> + </query> </queries> <filters> <filter xsi:type="termFilter" name="test_configurable_filter" field="test_configurable" value="$test_configurable$"/> + <filter xsi:type="termFilter" name="visibility_filter" field="visibility" value="$visibility$"/> </filters> <aggregations/> <from>0</from> diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_weight_products.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_weight_products.php index b672fbe9f8cec..3902e78d1fb55 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_weight_products.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/search_weight_products.php @@ -7,18 +7,8 @@ */ use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Catalog\Model\Product; -use Magento\Catalog\Model\Product\Attribute\Source\Status; -use Magento\Catalog\Model\Product\Type; -use Magento\Catalog\Model\Product\Visibility; -use Magento\Catalog\Setup\CategorySetup; -use Magento\ConfigurableProduct\Helper\Product\Options\Factory; -use Magento\ConfigurableProduct\Model\Product\Type\Configurable; -use Magento\Eav\Api\Data\AttributeOptionInterface; use Magento\TestFramework\Helper\Bootstrap; -Bootstrap::getInstance()->reinitialize(); - $objectManager = Bootstrap::getObjectManager(); /** @var ProductRepositoryInterface $productRepository */ From 4f1b50b1683e0bc3c00ee5d9d76aaa01b326cd80 Mon Sep 17 00:00:00 2001 From: Artem Cherednichenko <artemcherednichenkovasikievich@gmail.com> Date: Thu, 31 May 2018 13:26:13 +0300 Subject: [PATCH 0882/2023] Fix translations --- .../view/frontend/web/template/minicart/content.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html index 8bf1a87d34e6e..2daca51a2f5da 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html @@ -30,8 +30,12 @@ <span class="count" if="maxItemsToDisplay < getCartLineItemsCount()" text="maxItemsToDisplay"/> <translate args="'of'" if="maxItemsToDisplay < getCartLineItemsCount()"/> <span class="count" text="getCartLineItemsCount()"/> - <translate args="'Item in Cart'" if="getCartLineItemsCount() === 1"/> - <translate args="'Items in Cart'" if="getCartLineItemsCount() > 1"/> + <!-- ko if: (getCartLineItemsCount() === 1) --> + <span translate="'Item in Cart'"/> + <!--/ko--> + <!-- ko if: (getCartLineItemsCount() > 1) --> + <span translate="'Items in Cart'"/> + <!--/ko--> </div> <each args="getRegion('subtotalContainer')" render=""/> From 46d4116c8a7cc14a473fe23a1b22c92106404c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karla=20Saarem=C3=A4e?= <karlasaaremae@gmail.com> Date: Thu, 31 May 2018 14:34:48 +0300 Subject: [PATCH 0883/2023] swatches LESS rewrite Rewrote LESS code to suit better with Magneto Blank theme --- .../web/css/source/_module.less | 576 ++++++++++-------- 1 file changed, 315 insertions(+), 261 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Swatches/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Swatches/web/css/source/_module.less index 907180eb37444..0fcee34fda688 100644 --- a/app/design/frontend/Magento/blank/Magento_Swatches/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Swatches/web/css/source/_module.less @@ -4,289 +4,343 @@ // */ // -// Common +// Variables // _____________________________________________ - & when (@media-common = true) { - .swatch-attribute-label { - font-weight: bold; - position: relative; - } - - .swatch-attribute-label.required { - padding-right: 10px; - } - - .swatch-attribute-label[data-required="1"]:after { - content: '*'; - color: red; - position: absolute; - right: -11px; - top: -2px; - font-weight: bold; - font-size: 1em; - } +@swatch-attribute-option__selected__color: #646464; - .swatch-attribute-selected-option { - color: #646464; - padding-left: 17px; - } +@swatch-option__background: @color-gray94; +@swatch-option__border: @border-width__base solid #dadada; - .swatch-attribute-options { - margin-top: 10px; - } +@swatch-option__hover__border: @border-width__base solid @color-white; +@swatch-option__hover__color: @color-gray20; +@swatch-option__hover__outline: 1px solid @color-gray60; - .swatch-option { - padding: 1px 2px; - min-width: 30px; - max-width: 90px; - height: 20px; - float: left; - margin: 0 10px 5px 0; - text-align: center; - cursor: pointer; - position: relative; - border: 1px solid rgb(218, 218, 218); - overflow: hidden; - text-overflow: ellipsis; - } +@swatch-option__selected__border: @swatch-option__hover__border; +@swatch-option__selected__color: @swatch-option__hover__color; +@swatch-option__selected__outline: 2px solid @color-orange-red1; - .swatch-option.text { - background: #F0F0F0; - color: #686868; - font-size: 12px; - font-weight: 700; - line-height: 20px; - padding: 4px 8px; - min-width: 22px; - margin-right: 7px; - } - - .swatch-option.selected { - outline: 2px solid #ff5501; - border: 1px solid #fff; - color: #333; - } - - .swatch-option.text.selected { - background-color: #FFF !important; - } - - .clearfix:after { - content: ''; - visibility: hidden; - display: block; - height: 0; - clear: both; - } +@swatch-option__disabled__background: @color-red10; - .swatch-attribute.size .swatch-option, - .swatch-attribute.manufacturer .swatch-option { - background: rgb(240, 240, 240); - color: rgb(148, 148, 148); - } +// Text attributes +@swatch-option-text__background: @swatch-option__background; +@swatch-option-text__color: #686868; - .swatch-attribute.size .swatch-option.selected, - .swatch-attribute.manufacturer .swatch-option.selected { - color: black; - background: #fff; - border: 1px solid #fff; - } +@swatch-option-text__selected__background-color: @color-white !important; - .swatch-option:not(.disabled):hover { - outline: 1px solid #999; - border: 1px solid #fff; - color: #333; - } +// Size and Manufacturer attributes +@attr-swatch-option__background: @swatch-option__background; +@attr-swatch-option__color: #949494; - .swatch-option.image:not(.disabled):hover, - .swatch-option.color:not(.disabled):hover { - outline: 2px solid #ee0000; - border: 1px solid #fff; - } +@attr-swatch-option__selected__background: @color-white; +@attr-swatch-option__selected__border: @border-width__base solid @color-white; +@attr-swatch-option__selected__color: @color-black; - .swatch-option.disabled { - cursor: default; - } +// Image and Color swatch +@img-color-swatch-option__hover__border: @swatch-option__hover__border; +@img-color-swatch-option__hover__outline: 2px solid #ee0000; - .swatch-option.disabled:after { - content: ''; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - background: -moz-linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); - background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(42%, rgba(255, 255, 255, 0)), color-stop(43%, rgba(255, 255, 255, 1)), color-stop(46%, rgba(255, 255, 255, 1)), color-stop(47%, rgba(255, 82, 22, 1)), color-stop(53%, rgba(255, 82, 22, 1)), color-stop(54%, rgba(255, 255, 255, 1)), color-stop(57%, rgba(255, 255, 255, 1)), color-stop(58%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0))); - background: -webkit-linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); - background: -o-linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); - background: -ms-linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); - background: linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#00ffffff', GradientType=1); - } +// Tooltip +@swatch-option-tooltip__background: @color-white; +@swatch-option-tooltip__border: @swatch-option__border; +@swatch-option-tooltip__color: #949494; - .swatch-option-tooltip { - max-width: 140px; - max-height: 100%; - min-height: 20px; - min-width: 20px; - position: absolute; - padding: 5px; - background: #fff; - color: rgb(148, 148, 148); - border: 1px solid #adadad; - display: none; - z-index: 999; - text-align: center; - } +@swatch-option-tooltip-title__color: #282828; - .swatch-option-tooltip .corner, - .swatch-option-tooltip-layered .corner { - left: 40%; - position: absolute; - bottom: 0; - height: 8px; - } +@swatch-option-tooltip-layered__background: @swatch-option-tooltip__background; +@swatch-option-tooltip-layered__border: @swatch-option__border; +@swatch-option-tooltip-layered__color: @swatch-option-tooltip__color; - .swatch-option-tooltip .corner:after, - .swatch-option-tooltip-layered .corner:after { - content: ''; - position: relative; - top: 1px; - left: -15px; - width: 0; - height: 0; - border-style: solid; - border-width: 7px 7.5px 0 7.5px; - border-color: #fff transparent transparent transparent; - font-size: 1px; - } +@swatch-option-tooltip-layered-title__color: @swatch-option-tooltip-title__color; - .swatch-option-tooltip .corner:before, - .swatch-option-tooltip-layered .corner:before { - content: ''; - position: relative; - top: 2px; - left: 0; - width: 0; - height: 0; - border-style: solid; - border-width: 8px 8.5px 0 8.5px; - border-color: #adadad transparent transparent transparent; - font-size: 1px; - } +// Layered Features +@swatch-option-link-layered__focus__box-shadow: 0 0 3px 1px @color-sky-blue1; - .swatch-option-tooltip .image, - .swatch-option-tooltip-layered .image { - display: block; - height: 130px; - width: 130px; - margin: 0 auto; - } - - .swatch-option-tooltip .title { - max-width: 140px; - min-height: 20px; - max-height: 200px; - color: rgb(40, 40, 40); - text-align: center; - display: block; - overflow: hidden; - } - - .swatch-opt { - margin: 20px 0; - } - - .swatch-more { - display: inline-block; - margin: 2px 0; - text-decoration: none !important; - position: static; - z-index: 1; - } - - // Layered Features - .swatch-option-link-layered { - position: relative; - margin: 0 !important; - padding: 0 !important; - } - - .swatch-option-link-layered:focus>div { - box-shadow: 0 0 3px 1px #68a8e0; - } - - .swatch-option-tooltip-layered { - width: 140px; - position: absolute; - background: #fff; - color: rgb(148, 148, 148); - border: 1px solid #adadad; - display: none; - z-index: 999; - left: -47px; - } - - .swatch-visual-tooltip-layered { - height: 160px; - top: -170px; - } - - .swatch-textual-tooltip-layered { - height: 30px; - top: -40px; - } +// +// Common +// _____________________________________________ - .swatch-option-link-layered:hover>.swatch-option-tooltip-layered { - display: block; - } + & when (@media-common = true) { - .swatch-attribute-options .swatch-option-tooltip-layered .title { - width: 100%; - height: 20px; - position: absolute; - bottom: -5px; - left: 0; - color: rgb(40, 40, 40); - text-align: center; - margin-bottom: 10px; + .swatch { + &-attribute { + &-label { + font-weight: @font-weight__bold; + position: relative; + + &.required { + padding-right: @indent__s; + } + + &[data-required="1"]:after { + .lib-css(color, @form-field-label-asterisk__color); + content: '*'; + position: absolute; + right: -11px; + top: -2px; + font-weight: @font-weight__bold; + font-size: @font-size__base; + } + } + + &-selected-option { + .lib-css(color, @swatch-attribute-option__selected__color); + padding-left: 17px; + } + + &-options { + margin-top: @indent__s; + + .swatch-option-tooltip-layered .title { + .lib-css(color, @swatch-option-tooltip-layered-title__color); + width: 100%; + height: 20px; + position: absolute; + bottom: -5px; + left: 0; + text-align: center; + margin-bottom: @indent__s; + } + } + + &.size, + &.manufacturer { + .swatch-option { + .lib-css(background, @attr-swatch-option__background); + .lib-css(color, @attr-swatch-option__color); + + &.selected { + .lib-css(blackground, @attr-swatch-option__selected__background); + .lib-css(border, @attr-swatch-option__selected__border); + .lib-css(color, @attr-swatch-option__selected__color); + } + } + } + } + + &-option { + .lib-css(border, @swatch-option__border); + padding: 1px 2px; + min-width: 30px; + max-width: 90px; + height: 20px; + float: left; + margin: 0 @indent__s @indent__xs 0; + text-align: center; + cursor: pointer; + position: relative; + overflow: hidden; + text-overflow: ellipsis; + + &.text { + .lib-css(background, @swatch-option-text__background); + .lib-css(color, @swatch-option-text__color); + font-size: @font-size__s; + font-weight: @font-weight__bold; + line-height: 20px; + padding: 4px 8px; + min-width: 22px; + margin-right: 7px; + + &.selected { + .lib-css(background-color, @swatch-option-text__selected__background-color); + } + } + + &.selected { + .lib-css(outline, @swatch-option__selected__outline); + .lib-css(border, @swatch-option__selected__border); + .lib-css(color, @swatch-option__selected__color); + } + + &:not(.disabled):hover { + .lib-css(border, @swatch-option__hover__border); + .lib-css(color, @swatch-option__hover__color); + .lib-css(outline, @swatch-option__hover__outline); + } + + &.image, + &.color { + &:not(.disabled):hover { + .lib-css(border, @img-color-swatch-option__hover__border); + .lib-css(outline, @img-color-swatch-option__hover__outline); + } + } + + &.disabled { + cursor: default; + + &:after { + content: ''; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + + // ToDo: improve .lib-background-gradient() to support diagonal gradient + background: -moz-linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); + background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(42%, rgba(255, 255, 255, 0)), color-stop(43%, rgba(255, 255, 255, 1)), color-stop(46%, rgba(255, 255, 255, 1)), color-stop(47%, rgba(255, 82, 22, 1)), color-stop(53%, rgba(255, 82, 22, 1)), color-stop(54%, rgba(255, 255, 255, 1)), color-stop(57%, rgba(255, 255, 255, 1)), color-stop(58%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0))); + background: -webkit-linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); + background: -o-linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); + background: -ms-linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); + background: linear-gradient(to left top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 1) 43%, rgba(255, 255, 255, 1) 46%, rgba(255, 82, 22, 1) 47%, rgba(255, 82, 22, 1) 53%, rgba(255, 255, 255, 1) 54%, rgba(255, 255, 255, 1) 57%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, 0) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#00ffffff', GradientType=1); + } + } + &-disabled { + outline: none !important; + cursor: default; + border: 0; + + &:after { + .lib-css(background, @swatch-option__disabled__background); + .lib-rotate(-30deg); + content: ''; + position: absolute; + width: 42px; + height: 2px; + z-index: 995; + left: -4px; + top: 10px; + } + } + + &-loading { + .lib-url('Magento_Swatches/images/loader-2.gif'); + content: url("@{url}"); + } + + &-tooltip { + .lib-css(background, @swatch-option-tooltip__background); + .lib-css(border, @swatch-option-tooltip__border); + .lib-css(color, @swatch-option-tooltip__color); + max-width: 140px; + max-height: 100%; + min-height: 20px; + min-width: 20px; + position: absolute; + padding: @indent__xs; + display: none; + z-index: 999; + text-align: center; + + &, + &-layered { + .corner { + left: 40%; + position: absolute; + bottom: 0; + height: 8px; + + &:before, + &:after { + content: ''; + position: relative; + width: 0; + height: 0; + border-style: solid; + font-size: 1px; + } + + &:before { + top: 2px; + left: 0; + border-width: 8px 8.5px 0 8.5px; + border-color: #adadad transparent transparent transparent; + } + + &:after { + top: 1px; + left: -15px; + border-width: 7px 7.5px 0 7.5px; + border-color: #fff transparent transparent transparent; + } + } + + .image { + display: block; + height: 130px; + width: 130px; + margin: 0 auto; + } + } + + &-layered { + .lib-css(background, @swatch-option-tooltip-layered__background); + .lib-css(border, @swatch-option-tooltip-layered__border); + .lib-css(color, @swatch-option-tooltip-layered__color); + width: 140px; + position: absolute; + display: none; + z-index: 999; + left: -47px; + } + + .title { + .lib-css(color, @swatch-option-tooltip-title__color); + max-width: 140px; + min-height: 20px; + max-height: 200px; + text-align: center; + display: block; + overflow: hidden; + } + } + + &-link-layered { + position: relative; + margin: 0 !important; + padding: 0 !important; + + &:focus > div { + .lib-css(box-shadow, @swatch-option-link-layered__focus__box-shadow); + } + + &:hover > .swatch-option-tooltip-layered { + display: block; + } + } + } + + &-opt { + margin: @indent__base 0; + + &-listing { + margin-bottom: @indent__s; + } + } + + &-more { + display: inline-block; + margin: 2px 0; + text-decoration: none !important; + position: static; + z-index: 1; + } + + &-visual-tooltip-layered { + height: 160px; + top: -170px; + } + + &-textual-tooltip-layered { + height: 30px; + top: -40px; + } + + &-input { + left: -1000px; + position: absolute; + visibility: hidden; + } } - .swatch-option-disabled:after { + .clearfix:after { content: ''; - position: absolute; - width: 42px; - height: 2px; - background: red; - transform: rotate(-30deg); - -o-transform: rotate(-30deg); - -moz-transform: rotate(-30deg); - -ms-transform: rotate(-30deg); - -webkit-transform: rotate(-30deg); - z-index: 995; - left: -4px; - top: 10px; - } - - .swatch-option-disabled { - outline: none !important; - cursor: default; - border: 0; - } - - // Bugfix for Add To Cart button - .swatch-opt-listing { - margin-bottom: 10px; - } - - .swatch-option-loading { - content: url(../Magento_Swatches/images/loader-2.gif); - } - - .swatch-input { - left: -1000px; - position: absolute; visibility: hidden; + display: block; + height: 0; + clear: both; } } From ffda0cc977d1024f68a4b86a40096ff1f310f34e Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Thu, 31 May 2018 14:45:45 +0300 Subject: [PATCH 0884/2023] MAGETWO-90739: Out of stock options for configurable products still show up in search and layered navigation if Elasticsearch is enabled --- app/code/Magento/Elasticsearch/Model/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Elasticsearch/Model/Config.php b/app/code/Magento/Elasticsearch/Model/Config.php index 6f4e54e96fb9b..eb033e869290f 100644 --- a/app/code/Magento/Elasticsearch/Model/Config.php +++ b/app/code/Magento/Elasticsearch/Model/Config.php @@ -61,7 +61,7 @@ class Config implements ClientOptionsInterface * @param ScopeConfigInterface $scopeConfig * @param ClientResolver|null $clientResolver * @param EngineResolver|null $engineResolver - * @param string|null $prefix + * @param string $prefix */ public function __construct( ScopeConfigInterface $scopeConfig, From f8355aefb9b3253a13842ed968e91cdf91b9df1b Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Thu, 31 May 2018 15:28:13 +0300 Subject: [PATCH 0885/2023] MAGETWO-64173: Browser back button issue (Checkout pages) --- .../view/frontend/web/js/model/step-navigator.js | 11 ++++++++++- .../view/frontend/web/js/view/progress-bar.js | 5 +++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js index c707792111c82..0f2b0f4e26869 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js @@ -182,6 +182,15 @@ define([ }); }, + /** + * Sets window location hash. + * + * @param {String} hash + */ + setHash: function (hash) { + window.location.hash = hash; + }, + /** * Next step. */ @@ -199,7 +208,7 @@ define([ if (steps().length > activeIndex + 1) { code = steps()[activeIndex + 1].code; steps()[activeIndex + 1].isVisible(true); - window.location = window.checkoutConfig.checkoutUrl + '#' + code; + this.setHash(code); document.body.scrollTop = document.documentElement.scrollTop = 0; } } diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js b/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js index 72cf4e3d479c3..683a18d0e4ead 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js @@ -25,6 +25,11 @@ define([ initialize: function () { this._super(); window.addEventListener('hashchange', _.bind(stepNavigator.handleHash, stepNavigator)); + + if (!window.location.hash) { + stepNavigator.setHash(stepNavigator.steps().sort(stepNavigator.sortItems)[0].code); + } + stepNavigator.handleHash(); }, From 5542c81d42610c7ac5d15f1ff7aecf884f1f92fe Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Thu, 31 May 2018 18:09:16 +0300 Subject: [PATCH 0886/2023] MAGETWO-92134: [2.2.x] Payment Failed Email is not generated --- app/code/Magento/Sales/Model/Service/PaymentFailuresService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php b/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php index 6da1dc1b7e7cc..3a49bbce256ef 100644 --- a/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php +++ b/app/code/Magento/Sales/Model/Service/PaymentFailuresService.php @@ -283,7 +283,7 @@ private function getLocaleDate(): string */ private function getCustomerName(Quote $quote): string { - $customer = __('Guest'); + $customer = __('Guest')->render(); if (!$quote->getCustomerIsGuest()) { $customer = $quote->getCustomer()->getFirstname() . ' ' . $quote->getCustomer()->getLastname(); From 3ac0addc2d6e688d767686132ce1cf78639a2613 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 31 May 2018 18:17:27 +0300 Subject: [PATCH 0887/2023] MAGETWO-91104: [2.3.0] Using a multiselect product attribute with a custom source model in the adminhtml doesn't render selected value --- .../Product/Form/Modifier/EavTest.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php index 320ec821d7ffb..0426e389d9aeb 100755 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php @@ -462,16 +462,17 @@ public function testModifyData() * @param bool $productRequired * @param string|null $attrValue * @param array $expected + * @return void * @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::isProductExists * @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::setupAttributeMeta * @dataProvider setupAttributeMetaDataProvider */ public function testSetupAttributeMetaDefaultAttribute( $productId, - $productRequired, + bool $productRequired, $attrValue, - $expected - ) { + array $expected + ) : void { $configPath = 'arguments/data/config'; $groupCode = 'product-details'; $sortOrder = '0'; @@ -480,14 +481,14 @@ public function testSetupAttributeMetaDefaultAttribute( ['value' => 1.5, 'label' => 'Float label'], ['value' => true, 'label' => 'Boolean label'], ['value' => 'string', 'label' => 'String label'], - ['value' => ['test1', 'test2'], 'label' => 'Array label'] + ['value' => ['test1', 'test2'], 'label' => 'Array label'], ]; $attributeOptionsExpected = [ ['value' => '1', 'label' => 'Int label'], ['value' => '1.5', 'label' => 'Float label'], ['value' => '1', 'label' => 'Boolean label'], ['value' => 'string', 'label' => 'String label'], - ['value' => ['test1', 'test2'], 'label' => 'Array label'] + ['value' => ['test1', 'test2'], 'label' => 'Array label'], ]; $this->productMock->method('getId')->willReturn($productId); @@ -563,7 +564,7 @@ public function setupAttributeMetaDataProvider() 'source' => 'product-details', 'scopeLabel' => '', 'globalScope' => false, - 'sortOrder' => 0 + 'sortOrder' => 0, ], ], 'default_null_prod_not_new_and_not_required' => [ @@ -582,7 +583,7 @@ public function setupAttributeMetaDataProvider() 'source' => 'product-details', 'scopeLabel' => '', 'globalScope' => false, - 'sortOrder' => 0 + 'sortOrder' => 0, ], ], 'default_null_prod_new_and_not_required' => [ @@ -601,7 +602,7 @@ public function setupAttributeMetaDataProvider() 'source' => 'product-details', 'scopeLabel' => '', 'globalScope' => false, - 'sortOrder' => 0 + 'sortOrder' => 0, ], ], 'default_null_prod_new_and_required' => [ @@ -620,7 +621,7 @@ public function setupAttributeMetaDataProvider() 'source' => 'product-details', 'scopeLabel' => '', 'globalScope' => false, - 'sortOrder' => 0 + 'sortOrder' => 0, ], ] ]; From ed7fb27e198b3fe3879dfbd27a7ffb8f2cfd5071 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@magento.com> Date: Thu, 31 May 2018 11:36:44 -0500 Subject: [PATCH 0888/2023] MQE-1026: Stablize RE-develop branch --- .../Catalog/Section/StorefrontProductActionSection.xml | 2 +- .../SalesRule/ActionGroup/StorefrontSalesRuleActionGroup.xml | 1 + .../Test/AdminCreateCartPriceRuleForCouponCodeTest.xml | 1 + .../Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontProductActionSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontProductActionSection.xml index f9e034aa3ae58..c2360efc05fa4 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontProductActionSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/StorefrontProductActionSection.xml @@ -9,7 +9,7 @@ xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> <section name="StorefrontProductActionSection"> <element name="quantity" type="input" selector="#qty"/> - <element name="addToCart" type="button" selector="#product-addtocart-button" timeout="30"/> + <element name="addToCart" type="button" selector="#product-addtocart-button"/> <element name="addToCartButtonTitleIsAdding" type="text" selector="//button/span[text()='Adding...']"/> <element name="addToCartButtonTitleIsAdded" type="text" selector="//button/span[text()='Added']"/> <element name="addToCartButtonTitleIsAddToCart" type="text" selector="//button/span[text()='Add to Cart']"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/ActionGroup/StorefrontSalesRuleActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/ActionGroup/StorefrontSalesRuleActionGroup.xml index bba7a81a7c884..0027d9a71fff3 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/ActionGroup/StorefrontSalesRuleActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/ActionGroup/StorefrontSalesRuleActionGroup.xml @@ -49,6 +49,7 @@ <waitForPageLoad stepKey="waitForProductPageLoad"/> <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="{{quantity}}" stepKey="fillQuantity"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + <waitForPageLoad stepKey="waitForAddToCart"/> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> <waitForPageLoad stepKey="waitForCartPage"/> <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml index 33703d3a97072..29f7fedc33af5 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml @@ -74,6 +74,7 @@ <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + <waitForPageLoad stepKey="waitForAddToCart"/> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> <waitForPageLoad stepKey="waitForCartPage"/> <actionGroup ref="StorefrontApplyCouponActionGroup" stepKey="applyCoupon"> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml index b5b30ce3c265a..15a2d8cedc99c 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml @@ -66,6 +66,7 @@ <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + <waitForPageLoad stepKey="waitForAddToCart"/> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> <waitForPageLoad stepKey="waitForCartPage"/> <conditionalClick selector="{{StorefrontSalesRuleCartCouponSection.couponHeader}}" dependentSelector="{{StorefrontSalesRuleCartCouponSection.discountBlockActive}}" visible="false" stepKey="clickCouponHeader"/> From 44f954173ea25153a48ddb35613ef983f29663d7 Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@magento.com> Date: Thu, 31 May 2018 15:39:31 -0500 Subject: [PATCH 0889/2023] MC-142: Guest customer should be able to advance search downloadable product with product name MC-252: Guest customer should be able to advance search downloadable product with product sku MC-243: Guest customer should be able to advance search downloadable product with product description MC-245: Guest customer should be able to advance search downloadable product with product short description MC-246: Guest customer should be able to advance search downloadable product with product price - updated mftf tests --- .../Downloadable/Data/LinkData.xml | 2 +- ...ceCatalogSearchDownloadableProductTest.xml | 25 ++++++++----------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/LinkData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/LinkData.xml index 5099255b3a1f7..1498f4b96b3ab 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/LinkData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Data/LinkData.xml @@ -48,6 +48,6 @@ <data key="shareable">No</data> <data key="number_of_downloads">1000</data> <data key="sort_order">0</data> - <data key="link_file">https://static.magento.com/sites/all/themes/mag_redesign/images/magento-logo.svg</data> + <data key="link_url">https://static.magento.com/sites/all/themes/mag_redesign/images/magento-logo.svg</data> </entity> </entities> \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Test/AdvanceCatalogSearchDownloadableProductTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Test/AdvanceCatalogSearchDownloadableProductTest.xml index ef8fcf66e92de..34c8b0a815477 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Test/AdvanceCatalogSearchDownloadableProductTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Downloadable/Test/AdvanceCatalogSearchDownloadableProductTest.xml @@ -14,13 +14,12 @@ </annotations> <before> <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> - <!-- Uncomment after bug MQE-1023 is fixed --> - <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> <requiredEntity createDataKey="createProductOne"/> </createData> <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> <requiredEntity createDataKey="createProductOne"/> - </createData--> + </createData> </before> </test> <test name="AdvanceCatalogSearchDownloadableBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> @@ -29,13 +28,12 @@ </annotations> <before> <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> - <!-- Uncomment after bug MQE-1023 is fixed --> - <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> <requiredEntity createDataKey="createProductOne"/> </createData> <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> <requiredEntity createDataKey="createProductOne"/> - </createData--> + </createData> </before> </test> <test name="AdvanceCatalogSearchDownloadableByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> @@ -44,13 +42,12 @@ </annotations> <before> <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> - <!-- Uncomment after bug MQE-1023 is fixed --> - <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> <requiredEntity createDataKey="createProductOne"/> </createData> <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> <requiredEntity createDataKey="createProductOne"/> - </createData--> + </createData> </before> </test> <test name="AdvanceCatalogSearchDownloadableByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> @@ -59,13 +56,12 @@ </annotations> <before> <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> - <!-- Uncomment after bug MQE-1023 is fixed --> - <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> <requiredEntity createDataKey="createProductOne"/> </createData> <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> <requiredEntity createDataKey="createProductOne"/> - </createData--> + </createData> </before> </test> <test name="AdvanceCatalogSearchDownloadableByPriceTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> @@ -74,13 +70,12 @@ </annotations> <before> <createData entity="ApiDownloadableProduct" stepKey="createProductOne"/> - <!-- Uncomment after bug MQE-1023 is fixed --> - <!--createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> + <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink1"> <requiredEntity createDataKey="createProductOne"/> </createData> <createData entity="ApiDownloadableLink" stepKey="addDownloadableLink2"> <requiredEntity createDataKey="createProductOne"/> - </createData--> + </createData> </before> </test> </tests> From b6cd7410214405896eb02ea89c01bdc2bdf6316a Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@magento.com> Date: Thu, 31 May 2018 18:00:29 -0500 Subject: [PATCH 0890/2023] MC-139: Guest customer should be able to advance search bundle product with product name MC-143: Guest customer should be able to advance search bundle product with product sku MC-242: Guest customer should be able to advance search bundle product with product description MC-250: Guest customer should be able to advance search bundle product with product short description MC-251: Guest customer should be able to advance search bundle product with product price - added mftf tests --- .../Bundle/Data/BundleLinkData.xml | 21 +++ .../Bundle/Data/BundleOptionData.xml | 21 +++ .../Bundle/Data/CustomAttributeData.xml | 22 +++ .../Bundle/Data/ProductData.xml | 14 ++ .../Bundle/Metadata/bundle_link-meta.xml | 24 +++ .../Bundle/Metadata/bundle_option-meta.xml | 21 +++ .../Bundle/Metadata/bundle_options-meta.xml | 14 ++ .../AdvanceCatalogSearchBundleProductTest.xml | 151 ++++++++++++++++++ .../AdvanceCatalogSearchBundleProductTest.xml | 80 ++++++++++ 9 files changed, 368 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/BundleLinkData.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/BundleOptionData.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/CustomAttributeData.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_link-meta.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_option-meta.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_options-meta.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Test/AdvanceCatalogSearchBundleProductTest.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchBundleProductTest.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/BundleLinkData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/BundleLinkData.xml new file mode 100644 index 0000000000000..65add76a12af3 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/BundleLinkData.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="ApiBundleLink" type="bundle_link"> + <var key="sku" entityKey="sku" entityType="product2"/> + <var key="option_id" entityKey="option_id" entityType="bundle_options"/> + <var key="sku" entityKey="sku" entityType="product"/> + <data key="qty">1</data> + <data key="is_default">1</data> + <data key="price">1.11</data> + <data key="price_type">1</data> + <data key="can_change_quantity">1</data> + </entity> +</entities> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/BundleOptionData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/BundleOptionData.xml new file mode 100644 index 0000000000000..02f70ec15cab8 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/BundleOptionData.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="DropdownBundleOption" type="bundle_option"> + <data key="title" unique="suffix">bundle-option-dropdown</data> + <data key="required">true</data> + <data key="type">dropdown</data> + <data key="position">1</data> + <var key="sku" entityKey="sku" entityType="product2"/> + </entity> + <entity name="AllBundleOptions" type="bundle_options"> + <var key="sku" entityKey="sku" entityType="product"/> + </entity> +</entities> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/CustomAttributeData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/CustomAttributeData.xml new file mode 100644 index 0000000000000..c7f150e7ad6fb --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/CustomAttributeData.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="CustomAttributeDynamicPrice" type="custom_attribute"> + <data key="attribute_code">price_type</data> + <data key="value">0</data> + </entity> + <entity name="CustomAttributeFixPrice" type="custom_attribute"> + <data key="attribute_code">price_type</data> + <data key="value">1</data> + </entity> + <entity name="CustomAttributePriceView" type="custom_attribute"> + <data key="attribute_code">price_view</data> + <data key="value">1</data> + </entity> +</entities> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/ProductData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/ProductData.xml index a8598ded6ec17..69741ccd5021a 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/ProductData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Data/ProductData.xml @@ -19,4 +19,18 @@ <data key="status">1</data> <data key="urlKey" unique="suffix">bundleproduct</data> </entity> + <entity name="ApiBundleProduct" type="product2"> + <data key="name" unique="suffix">Api Bundle Product</data> + <data key="sku" unique="suffix">api-bundle-product</data> + <data key="type_id">bundle</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="status">1</data> + <data key="urlKey" unique="suffix">api-bundle-product</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute">ApiProductDescription</requiredEntity> + <requiredEntity type="custom_attribute">ApiProductShortDescription</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributeDynamicPrice</requiredEntity> + <requiredEntity type="custom_attribute">CustomAttributePriceView</requiredEntity> + </entity> </entities> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_link-meta.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_link-meta.xml new file mode 100644 index 0000000000000..be881a7e98d65 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_link-meta.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd"> + <operation name="CreateBundleLink" dataType="bundle_link" type="create" auth="adminOauth" url="/V1/bundle-products/{sku}/links/{option_id}" method="POST"> + <contentType>application/json</contentType> + <object dataType="bundle_link" key="linkedProduct"> + <field key="sku">string</field> + <field key="option_id">integer</field> + <field key="qty">integer</field> + <field key="position">integer</field> + <field key="is_default">boolean</field> + <field key="price">number</field> + <field key="price_type">integer</field> + <field key="can_change_quantity">integer</field> + </object> + </operation> +</operations> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_option-meta.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_option-meta.xml new file mode 100644 index 0000000000000..991c01ec4c6f0 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_option-meta.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd"> + <operation name="CreateBundleOption" dataType="bundle_option" type="create" auth="adminOauth" url="/V1/bundle-products/options/add" method="POST"> + <contentType>application/json</contentType> + <object dataType="bundle_option" key="option"> + <field key="title">string</field> + <field key="required">boolean</field> + <field key="type">string</field> + <field key="position">integer</field> + <field key="sku">string</field> + </object> + </operation> +</operations> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_options-meta.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_options-meta.xml new file mode 100644 index 0000000000000..a81d5dda6a40b --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Metadata/bundle_options-meta.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd"> + <operation name="GetAllBundleOptions" dataType="bundle_options" type="get" auth="adminOauth" url="/V1/bundle-products/{sku}/options/all" method="GET"> + <contentType>application/json</contentType> + </operation> +</operations> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Test/AdvanceCatalogSearchBundleProductTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Test/AdvanceCatalogSearchBundleProductTest.xml new file mode 100644 index 0000000000000..375fe387ed424 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Bundle/Test/AdvanceCatalogSearchBundleProductTest.xml @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdvanceCatalogSearchBundleByNameTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiProductWithDescription" stepKey="simple1" before="simple2"/> + <createData entity="ApiProductWithDescription" stepKey="simple2" before="createProductOne"/> + <createData entity="ApiBundleProduct" stepKey="createProductOne"/> + <createData entity="DropdownBundleOption" stepKey="bundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <getData entity="AllBundleOptions" index="0" stepKey="getBundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </getData> + <createData entity="ApiBundleLink" stepKey="createBundleLink1"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createBundleLink2"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + </test> + <test name="AdvanceCatalogSearchBundleBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiProductWithDescription" stepKey="simple1" before="simple2"/> + <createData entity="ApiProductWithDescription" stepKey="simple2" before="createProductOne"/> + <createData entity="ApiBundleProduct" stepKey="createProductOne"/> + <createData entity="DropdownBundleOption" stepKey="bundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <getData entity="AllBundleOptions" index="0" stepKey="getBundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </getData> + <createData entity="ApiBundleLink" stepKey="createBundleLink1"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createBundleLink2"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + </test> + <test name="AdvanceCatalogSearchBundleByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiProductWithDescription" stepKey="simple1" before="simple2"/> + <createData entity="ApiProductWithDescription" stepKey="simple2" before="createProductOne"/> + <createData entity="ApiBundleProduct" stepKey="createProductOne"/> + <createData entity="DropdownBundleOption" stepKey="bundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <getData entity="AllBundleOptions" index="0" stepKey="getBundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </getData> + <createData entity="ApiBundleLink" stepKey="createBundleLink1"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createBundleLink2"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + </test> + <test name="AdvanceCatalogSearchBundleByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiProductWithDescription" stepKey="simple1" before="simple2"/> + <createData entity="ApiProductWithDescription" stepKey="simple2" before="createProductOne"/> + <createData entity="ApiBundleProduct" stepKey="createProductOne"/> + <createData entity="DropdownBundleOption" stepKey="bundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <getData entity="AllBundleOptions" index="0" stepKey="getBundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </getData> + <createData entity="ApiBundleLink" stepKey="createBundleLink1"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createBundleLink2"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + </test> + <test name="AdvanceCatalogSearchBundleByPriceTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="ApiProductWithDescription" stepKey="simple1" before="simple2"/> + <createData entity="ApiProductWithDescription" stepKey="simple2" before="createProductOne"/> + <createData entity="ApiBundleProduct" stepKey="createProductOne"/> + <createData entity="DropdownBundleOption" stepKey="bundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </createData> + <getData entity="AllBundleOptions" index="0" stepKey="getBundleOption"> + <requiredEntity createDataKey="createProductOne"/> + </getData> + <createData entity="ApiBundleLink" stepKey="createBundleLink1"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple1"/> + </createData> + <createData entity="ApiBundleLink" stepKey="createBundleLink2"> + <requiredEntity createDataKey="createProductOne"/> + <requiredEntity createDataKey="getBundleOption"/> + <requiredEntity createDataKey="simple2"/> + </createData> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </before> + </test> +</tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchBundleProductTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchBundleProductTest.xml new file mode 100644 index 0000000000000..a94918313c206 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/CatalogSearch/Test/AdvanceCatalogSearchBundleProductTest.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdvanceCatalogSearchBundleByNameTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Bundle product with product name"/> + <description value="Guest customer should be able to advance search Bundle product with product name"/> + <severity value="MAJOR"/> + <testCaseId value="MC-139"/> + <group value="CatalogSearch"/> + </annotations> + </test> + <test name="AdvanceCatalogSearchBundleBySkuTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Bundle product with product sku"/> + <description value="Guest customer should be able to advance search Bundle product with product sku"/> + <severity value="MAJOR"/> + <testCaseId value="MC-143"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByProductSkuActionGroup" stepKey="search"> + <argument name="sku" value="$$createProductOne.sku$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchBundleByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Bundle product with product description"/> + <description value="Guest customer should be able to advance search Bundle product with product description"/> + <severity value="MAJOR"/> + <testCaseId value="MC-242"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByDescriptionActionGroup" stepKey="search"> + <argument name="description" value="$$createProductOne.custom_attributes[description]$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchBundleByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Bundle product with product short description"/> + <description value="Guest customer should be able to advance search Bundle product with product short description"/> + <severity value="MAJOR"/> + <testCaseId value="MC-250"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByShortDescriptionActionGroup" stepKey="search"> + <argument name="shortDescription" value="$$createProductOne.custom_attributes[short_description]$$"/> + </actionGroup> + </test> + <test name="AdvanceCatalogSearchBundleByPriceTest" extends="AdvanceCatalogSearchSimpleProductByNameTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Advanced Catalog Product Search for all product types"/> + <title value="Guest customer should be able to advance search Bundle product with product price"/> + <description value="Guest customer should be able to advance search Bundle product with product price"/> + <severity value="MAJOR"/> + <testCaseId value="MC-251"/> + <group value="CatalogSearch"/> + </annotations> + <actionGroup ref="StorefrontAdvancedCatalogSearchByProductNameAndPriceActionGroup" stepKey="search"> + <argument name="name" value="$$createProductOne.name$$"/> + <argument name="priceFrom" value="$$simple1.price$$"/> + <argument name="priceTo" value="$$simple1.price$$"/> + </actionGroup> + </test> +</tests> From 1d510977b021079681fe6b723fba0c45ac174fc9 Mon Sep 17 00:00:00 2001 From: vgelani <vishalgelani99@gmail.com> Date: Mon, 28 May 2018 11:32:28 +0530 Subject: [PATCH 0891/2023] Fixed typo error --- app/code/Magento/Config/Block/System/Config/Form.php | 2 +- .../Model/Import/Product/Type/Configurable.php | 2 +- app/code/Magento/Customer/Model/Session.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Config/Block/System/Config/Form.php b/app/code/Magento/Config/Block/System/Config/Form.php index c17df229cf549..81e39a83296d7 100644 --- a/app/code/Magento/Config/Block/System/Config/Form.php +++ b/app/code/Magento/Config/Block/System/Config/Form.php @@ -709,7 +709,7 @@ protected function _getAdditionalElementTypes() } /** - * Temporary moved those $this->getRequest()->getParam('blabla') from the code accross this block + * Temporary moved those $this->getRequest()->getParam('blabla') from the code across this block * to getBlala() methods to be later set from controller with setters */ diff --git a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php index 64a0c23139c01..151bf5aa9263e 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php @@ -629,7 +629,7 @@ protected function _insertData() } /** - * Get new supper attribute id. + * Get new super attribute id. * * @return int */ diff --git a/app/code/Magento/Customer/Model/Session.php b/app/code/Magento/Customer/Model/Session.php index 71b0297fdd114..680e68b5c4c0f 100644 --- a/app/code/Magento/Customer/Model/Session.php +++ b/app/code/Magento/Customer/Model/Session.php @@ -555,7 +555,7 @@ public function setAfterAuthUrl($url) } /** - * Reset core session hosts after reseting session ID + * Reset core session hosts after resetting session ID * * @return $this */ From 9e4cc7b5f093321991a179d826505da27ea977c7 Mon Sep 17 00:00:00 2001 From: Marcel Hauri <marcel@hauri.me> Date: Fri, 1 Jun 2018 08:34:58 +0200 Subject: [PATCH 0892/2023] [forwardpport] fixes in config module #15511 --- app/code/Magento/Config/Model/Config/Importer.php | 2 +- .../Test/Unit/Block/System/Config/Form/Field/ImageTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Config/Model/Config/Importer.php b/app/code/Magento/Config/Model/Config/Importer.php index e65a90c593e84..a54af2ead5048 100644 --- a/app/code/Magento/Config/Model/Config/Importer.php +++ b/app/code/Magento/Config/Model/Config/Importer.php @@ -124,7 +124,7 @@ public function import(array $data) $this->scopeConfig->clean(); } - $this->state->emulateAreaCode(Area::AREA_ADMINHTML, function () use ($changedData, $data) { + $this->state->emulateAreaCode(Area::AREA_ADMINHTML, function () use ($changedData) { $this->scope->setCurrentScope(Area::AREA_ADMINHTML); // Invoke saving of new values. diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/ImageTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/ImageTest.php index 1679ac75ad02c..8a005a52ab614 100644 --- a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/ImageTest.php +++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/ImageTest.php @@ -72,7 +72,7 @@ public function testGetElementHtmlWithValue() 'showInWebsite' => '1', 'showInStore' => '1', 'label' => null, - 'backend_model' => \Magento\BackendModelConfig\Backend\Image::class, + 'backend_model' => \Magento\Config\Model\Config\Backend\Image::class, 'upload_dir' => [ 'config' => 'system/filesystem/media', 'scope_info' => '1', From 647ad8a2231af88ead3622b91127f32b36fa18f8 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Fri, 1 Jun 2018 11:15:17 +0300 Subject: [PATCH 0893/2023] MAGETWO-50831: Impossible specify Bundle option title on store view level --- .../Initialization/Helper/Plugin/Bundle.php | 5 + .../Magento/Bundle/Model/OptionRepository.php | 2 +- .../Bundle/Model/Product/SaveHandler.php | 122 ++++++++++++------ .../Bundle/Model/ResourceModel/Option.php | 60 ++------- .../Helper/Plugin/BundleTest.php | 23 ++++ .../Bundle/Model/Product/SaveHandlerTest.php | 86 ++++++++++++ .../Model/Export/RowCustomizerTest.php | 48 +++++++ 7 files changed, 256 insertions(+), 90 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Model/Product/SaveHandlerTest.php diff --git a/app/code/Magento/Bundle/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Bundle.php b/app/code/Magento/Bundle/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Bundle.php index 7f21d9e69c6e0..3c9eac68eb9e4 100644 --- a/app/code/Magento/Bundle/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Bundle.php +++ b/app/code/Magento/Bundle/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Bundle.php @@ -105,8 +105,13 @@ public function afterInitialize( if ($result['bundle_options'] && !$compositeReadonly) { $product->setBundleOptionsData($result['bundle_options']); } + $this->processBundleOptionsData($product); $this->processDynamicOptionsData($product); + } elseif (!$compositeReadonly) { + $extension = $product->getExtensionAttributes(); + $extension->setBundleProductOptions([]); + $product->setExtensionAttributes($extension); } $affectProductSelections = (bool)$this->request->getPost('affect_bundle_product_selections'); diff --git a/app/code/Magento/Bundle/Model/OptionRepository.php b/app/code/Magento/Bundle/Model/OptionRepository.php index a70f4af56e989..59e658b08df28 100644 --- a/app/code/Magento/Bundle/Model/OptionRepository.php +++ b/app/code/Magento/Bundle/Model/OptionRepository.php @@ -234,7 +234,7 @@ protected function updateOptionSelection( */ private function getProduct($sku) { - $product = $this->productRepository->get($sku, true); + $product = $this->productRepository->get($sku, true, null, true); if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { throw new InputException(__('This is implemented for bundle products only.')); } diff --git a/app/code/Magento/Bundle/Model/Product/SaveHandler.php b/app/code/Magento/Bundle/Model/Product/SaveHandler.php index e5fa688c7fece..6a860bab4fb7b 100644 --- a/app/code/Magento/Bundle/Model/Product/SaveHandler.php +++ b/app/code/Magento/Bundle/Model/Product/SaveHandler.php @@ -5,7 +5,6 @@ */ namespace Magento\Bundle\Model\Product; -use Magento\Bundle\Api\Data\OptionInterface; use Magento\Bundle\Model\Option\SaveAction; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Bundle\Api\ProductOptionRepositoryInterface as OptionRepository; @@ -58,36 +57,6 @@ public function __construct( ?: ObjectManager::getInstance()->get(MetadataPool::class); } - /** - * @param ProductInterface $bundle - * @param OptionInterface[] $currentOptions - * - * @return void - */ - private function removeOldOptions( - ProductInterface $bundle, - array $currentOptions - ) { - $oldOptions = $this->optionRepository->getList($bundle->getSku()); - if ($oldOptions) { - $remainingOptions = []; - $metadata - = $this->metadataPool->getMetadata(ProductInterface::class); - $productId = $bundle->getData($metadata->getLinkField()); - - foreach ($currentOptions as $option) { - $remainingOptions[] = $option->getOptionId(); - } - foreach ($oldOptions as $option) { - if (!in_array($option->getOptionId(), $remainingOptions)) { - $option->setParentId($productId); - $this->removeOptionLinks($bundle->getSku(), $option); - $this->optionRepository->delete($option); - } - } - } - } - /** * @param object $entity * @param array $arguments @@ -98,24 +67,31 @@ private function removeOldOptions( */ public function execute($entity, $arguments = []) { - /** @var \Magento\Bundle\Api\Data\OptionInterface[] $options */ - $options = $entity->getExtensionAttributes()->getBundleProductOptions() ?: []; + /** @var \Magento\Bundle\Api\Data\OptionInterface[] $bundleProductOptions */ + $bundleProductOptions = $entity->getExtensionAttributes()->getBundleProductOptions() ?: []; //Only processing bundle products. - if ($entity->getTypeId() !== 'bundle' || empty($options)) { + if ($entity->getTypeId() !== Type::TYPE_CODE || empty($bundleProductOptions)) { return $entity; } - /** @var ProductInterface $entity */ - //Removing old options + + $existingBundleProductOptions = $this->optionRepository->getList($entity->getSku()); + $existingOptionsIds = !empty($existingBundleProductOptions) + ? $this->getOptionIds($existingBundleProductOptions) + : []; + $optionIds = !empty($bundleProductOptions) + ? $this->getOptionIds($bundleProductOptions) + : []; + if (!$entity->getCopyFromView()) { - $this->removeOldOptions($entity, $options); - } - //Saving active options. - foreach ($options as $option) { - $this->optionSave->save($entity, $option); + $this->processRemovedOptions($entity->getSku(), $existingOptionsIds, $optionIds); + $newOptionsIds = array_diff($optionIds, $existingOptionsIds); + $this->saveOptions($entity, $bundleProductOptions, $newOptionsIds); + } else { + //save only labels and not selections + product links + $this->saveOptions($entity, $bundleProductOptions); + $entity->setCopyFromView(false); } - $entity->setCopyFromView(false); - return $entity; } @@ -133,4 +109,64 @@ protected function removeOptionLinks($entitySku, $option) } } } + + /** + * Perform save for all options entities. + * + * @param object $entity + * @param array $options + * @param array $newOptionsIds + * @return void + */ + private function saveOptions($entity, array $options, array $newOptionsIds = []): void + { + foreach ($options as $option) { + if (in_array($option->getOptionId(), $newOptionsIds, true)) { + $option->setOptionId(null); + } + + $this->optionSave->save($entity, $option); + } + } + + /** + * Get options ids from array of the options entities. + * + * @param array $options + * @return array + */ + private function getOptionIds(array $options): array + { + $optionIds = []; + + if (empty($options)) { + return $optionIds; + } + + /** @var \Magento\Bundle\Api\Data\OptionInterface $option */ + foreach ($options as $option) { + if ($option->getOptionId()) { + $optionIds[] = $option->getOptionId(); + } + } + + return $optionIds; + } + + /** + * Removes old options that no longer exists. + * + * @param string $entitySku + * @param array $existingOptionsIds + * @param array $optionIds + * @return void + */ + private function processRemovedOptions(string $entitySku, array $existingOptionsIds, array $optionIds): void + { + foreach (array_diff($existingOptionsIds, $optionIds) as $optionId) { + $option = $this->optionRepository->get($entitySku, $optionId); + $this->removeOptionLinks($entitySku, $option); + $this->optionRepository->delete($option); + } + } } diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Option.php b/app/code/Magento/Bundle/Model/ResourceModel/Option.php index 46fd8b910f6f1..7babd0b349f02 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Option.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Option.php @@ -81,39 +81,29 @@ protected function _afterSave(\Magento\Framework\Model\AbstractModel $object) { parent::_afterSave($object); - $conditions = [ + $condition = [ 'option_id = ?' => $object->getId(), 'store_id = ? OR store_id = 0' => $object->getStoreId(), 'parent_product_id = ?' => $object->getParentId() ]; $connection = $this->getConnection(); + $connection->delete($this->getTable('catalog_product_bundle_option_value'), $condition); - if ($this->isOptionPresent($conditions)) { - $connection->update( - $this->getTable('catalog_product_bundle_option_value'), - [ - 'title' => $object->getTitle() - ], - $conditions - ); - } else { - $data = new \Magento\Framework\DataObject(); - $data->setOptionId($object->getId()) - ->setStoreId($object->getStoreId()) - ->setParentProductId($object->getParentId()) - ->setTitle($object->getTitle()); + $data = new \Magento\Framework\DataObject(); + $data->setOptionId($object->getId()) + ->setStoreId($object->getStoreId()) + ->setParentProductId($object->getParentId()) + ->setTitle($object->getTitle()); - $connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData()); + $connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData()); - /** - * also saving default value if this store view scope - */ - if ($object->getStoreId()) { - $data->setStoreId(0); - $data->setTitle($object->getDefaultTitle()); - $connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData()); - } + /** + * also saving default fallback value + */ + if (0 !== (int)$object->getStoreId()) { + $data->setStoreId(0)->setTitle($object->getDefaultTitle()); + $connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData()); } return $this; @@ -218,26 +208,4 @@ public function save(\Magento\Framework\Model\AbstractModel $object) return $this; } - - /** - * Is Bundle option present in the database - * - * @param array $conditions - * - * @return bool - */ - private function isOptionPresent($conditions) - { - $connection = $this->getConnection(); - - $select = $connection->select()->from($this->getTable('catalog_product_bundle_option_value')); - foreach ($conditions as $condition => $conditionValue) { - $select->where($condition, $conditionValue); - } - $select->limit(1); - - $rowSelect = $connection->fetchRow($select); - - return (is_array($rowSelect) && !empty($rowSelect)); - } } diff --git a/app/code/Magento/Bundle/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/BundleTest.php b/app/code/Magento/Bundle/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/BundleTest.php index 59a2190a43e0c..1fa7f186786ae 100644 --- a/app/code/Magento/Bundle/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/BundleTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/BundleTest.php @@ -163,4 +163,27 @@ public function testAfterInitializeIfBundleSelectionsAndCustomOptionsExist() $this->productMock->expects($this->once())->method('setCanSaveBundleSelections')->with(false); $this->model->afterInitialize($this->subjectMock, $this->productMock); } + + /** + * @return void + */ + public function testAfterInitializeIfBundleOptionsNotExist(): void + { + $valueMap = [ + ['bundle_options', null, null], + ['affect_bundle_product_selections', null, false], + ]; + $this->requestMock->expects($this->any())->method('getPost')->will($this->returnValueMap($valueMap)); + $extentionAttribute = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductExtensionInterface::class) + ->disableOriginalConstructor() + ->setMethods(['setBundleProductOptions']) + ->getMockForAbstractClass(); + $extentionAttribute->expects($this->once())->method('setBundleProductOptions')->with([]); + $this->productMock->expects($this->any())->method('getCompositeReadonly')->will($this->returnValue(false)); + $this->productMock->expects($this->once())->method('getExtensionAttributes')->willReturn($extentionAttribute); + $this->productMock->expects($this->once())->method('setExtensionAttributes')->with($extentionAttribute); + $this->productMock->expects($this->once())->method('setCanSaveBundleSelections')->with(false); + + $this->model->afterInitialize($this->subjectMock, $this->productMock); + } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/SaveHandlerTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/SaveHandlerTest.php new file mode 100644 index 0000000000000..46bfbea3eebd7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/SaveHandlerTest.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Model\Product; + +use Magento\Catalog\Api\ProductRepositoryInterface; + +/** + * Test class for \Magento\Bundle\Model\Product\SaveHandler + * The tested class used indirectly + * + * @magentoDataFixture Magento/Bundle/_files/product.php + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDbIsolation disabled + * @magentoAppIsolation enabled + */ +class SaveHandlerTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + private $objectManager; + + /** + * @var \Magento\Store\Model\Store + */ + private $store; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->store = $this->objectManager->create(\Magento\Store\Model\Store::class); + /** @var ProductRepositoryInterface $productRepository */ + $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + } + + public function testOptionTitlesOnDifferentStores() + { + /** + * @var \Magento\Bundle\Model\Product\OptionList $optionList + */ + $optionList = $this->objectManager->create(\Magento\Bundle\Model\Product\OptionList::class); + + $secondStoreId = $this->store->load('fixture_second_store')->getId(); + $thirdStoreId = $this->store->load('fixture_third_store')->getId(); + + $product = $this->productRepository->get('bundle-product', true, $secondStoreId, true); + $options = $optionList->getItems($product); + $title = $options[0]->getTitle(); + $newTitle = $title . ' ' . $this->store->load('fixture_second_store')->getCode(); + $options[0]->setTitle($newTitle); + $extension = $product->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $product->setExtensionAttributes($extension); + $product->save(); + + $product = $this->productRepository->get('bundle-product', true, $thirdStoreId, true); + $options = $optionList->getItems($product); + $newTitle = $title . ' ' . $this->store->load('fixture_third_store')->getCode(); + $options[0]->setTitle($newTitle); + $extension = $product->getExtensionAttributes(); + $extension->setBundleProductOptions($options); + $product->setExtensionAttributes($extension); + $product->save(); + + $product = $this->productRepository->get('bundle-product', false, $secondStoreId, true); + $options = $optionList->getItems($product); + $this->assertEquals(1, count($options)); + $this->assertEquals( + $title . ' ' . $this->store->load('fixture_second_store')->getCode(), + $options[0]->getTitle() + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php b/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php index 6f81421c902f6..6a7d0f2e51c20 100644 --- a/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php +++ b/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php @@ -56,4 +56,52 @@ public function testPrepareData() $this->assertEquals([], $this->model->addData([], $ids['simple'])); $this->assertEquals($parsedAdditionalAttributes, $result['additional_attributes']); } + + /** + * @magentoDataFixture Magento/Store/_files/second_store.php + * @magentoDataFixture Magento/Bundle/_files/product.php + * @magentoDbIsolation disabled + */ + public function testPrepareDataWithDifferentStoreValues() + { + $storeCode = 'default'; + $expectedNames = [ + 'name' => 'Bundle Product Items', + 'name_' . $storeCode => 'Bundle Product Items_' . $storeCode + ]; + $parsedAdditionalAttributes = 'text_attribute=!@#$%^&*()_+1234567890-=|\\:;"\'<,>.?/' + . ',text_attribute2=,'; + $allAdditionalAttributes = $parsedAdditionalAttributes . ',weight_type=0,price_type=1'; + $collection = $this->objectManager->get(\Magento\Catalog\Model\ResourceModel\Product\Collection::class); + /** @var \Magento\Store\Model\Store $store */ + $store = $this->objectManager->create(\Magento\Store\Model\Store::class); + $store->load($storeCode, 'code'); + /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); + $product = $productRepository->get('bundle-product', 1, $store->getId()); + + $extension = $product->getExtensionAttributes(); + $options = $extension->getBundleProductOptions(); + + foreach ($options as $productOption) { + $productOption->setTitle($productOption->getTitle() . '_' . $store->getCode()); + } + $extension->setBundleProductOptions($options); + $product->setExtensionAttributes($extension); + $productRepository->save($product); + $this->model->prepareData($collection, [$product->getId()]); + $result = $this->model->addData(['additional_attributes' => $allAdditionalAttributes], $product->getId()); + $bundleValues = array_map( + function ($input) { + $data = explode('=', $input); + return [$data[0] => $data[1]]; + }, + explode(',', $result['bundle_values']) + ); + $actualNames = [ + 'name' => array_column($bundleValues, 'name')[0], + 'name' . '_' . $store->getCode() => array_column($bundleValues, 'name' . '_' . $store->getCode())[0] + ]; + self::assertSame($expectedNames, $actualNames); + } } From 632926d7008c26096003a3a41d69e05dedb8aeb9 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Fri, 1 Jun 2018 11:44:45 +0300 Subject: [PATCH 0894/2023] MAGETWO-90739: Out of stock options for configurable products still show up in search and layered navigation if Elasticsearch is enabled --- app/code/Magento/Elasticsearch/Model/Config.php | 12 +++++++++--- .../Elasticsearch/Model/Indexer/IndexHandlerTest.php | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Model/Config.php b/app/code/Magento/Elasticsearch/Model/Config.php index eb033e869290f..3d55979dfcee8 100644 --- a/app/code/Magento/Elasticsearch/Model/Config.php +++ b/app/code/Magento/Elasticsearch/Model/Config.php @@ -6,6 +6,7 @@ namespace Magento\Elasticsearch\Model; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Search\EngineResolverInterface; use Magento\Search\Model\EngineResolver; use Magento\Store\Model\ScopeInterface; use Magento\AdvancedSearch\Model\Client\ClientOptionsInterface; @@ -55,23 +56,28 @@ class Config implements ClientOptionsInterface */ private $clientResolver; + /** + * @var EngineResolverInterface + */ + private $engineResolver; + /** * Constructor * * @param ScopeConfigInterface $scopeConfig * @param ClientResolver|null $clientResolver - * @param EngineResolver|null $engineResolver + * @param EngineResolverInterface|null $engineResolver * @param string $prefix */ public function __construct( ScopeConfigInterface $scopeConfig, ClientResolver $clientResolver = null, - EngineResolver $engineResolver = null, + EngineResolverInterface $engineResolver = null, $prefix = null ) { $this->scopeConfig = $scopeConfig; $this->clientResolver = $clientResolver ?: ObjectManager::getInstance()->get(ClientResolver::class); - $this->engineResolver = $engineResolver ?: ObjectManager::getInstance()->get(EngineResolver::class); + $this->engineResolver = $engineResolver ?: ObjectManager::getInstance()->get(EngineResolverInterface::class); $this->prefix = $prefix ?: $this->clientResolver->getCurrentEngine(); } diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php index 36d3c809242fc..014aaf7679bc9 100755 --- a/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/Model/Indexer/IndexHandlerTest.php @@ -190,6 +190,7 @@ public function testReindexRowAfterDelete(): void } /** + * @magentoDbIsolation enabled * @magentoAppArea adminhtml * @magentoConfigFixture default/catalog/search/engine elasticsearch * @magentoConfigFixture current_store catalog/search/elasticsearch_index_prefix indexerhandlertest From 513f1e0c2a60f6f4d367c7d3beecfd4a936113f3 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Fri, 1 Jun 2018 12:39:51 +0300 Subject: [PATCH 0895/2023] MAGETWO-91803: Double click (not too fast) on proceed to check out after view edit mini cart returns empty shopping cart --- .../Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js b/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js index f0679c657ab90..0bb0a53ce0a6b 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js @@ -22,6 +22,7 @@ define([ return false; } + $(element).attr('disabled', true); location.href = config.checkoutUrl; }); From 075a64c2c3aad5da6cdcc2fb18061cff6424a67c Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Fri, 1 Jun 2018 13:10:25 +0300 Subject: [PATCH 0896/2023] MAGETWO-90349: Template file 'header.html' is not found. --- .../Test/Unit/Model/AbstractTemplateTest.php | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php index 46f3fecfb8848..35d562fa7e5ec 100644 --- a/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php @@ -117,10 +117,11 @@ protected function setUp() /** * Return the model under test with additional methods mocked. * - * @param $mockedMethods array + * @param array $mockedMethods + * @param array $data * @return \Magento\Email\Model\Template|\PHPUnit_Framework_MockObject_MockObject */ - protected function getModelMock(array $mockedMethods = []) + protected function getModelMock(array $mockedMethods = [], array $data = []) { $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); return $this->getMockForAbstractClass( @@ -136,7 +137,8 @@ protected function getModelMock(array $mockedMethods = []) 'scopeConfig' => $this->scopeConfig, 'emailConfig' => $this->emailConfig, 'filterFactory' => $this->filterFactory, - 'templateFactory' => $this->templateFactory + 'templateFactory' => $this->templateFactory, + 'data' => $data, ] ), '', @@ -431,4 +433,17 @@ public function testGetDesignConfig() $expectedConfig = ['area' => 'test_area', 'store' => 2]; $this->assertEquals($expectedConfig, $model->getDesignConfig()->getData()); } + + /** + * @return void + */ + public function testSetForcedAreaWhenAreIsSet(): void + { + $templateId = 'test_template'; + $model = $this->getModelMock([], ['area' => 'frontend']); + + $this->emailConfig->expects($this->never())->method('getTemplateArea'); + + $model->setForcedArea($templateId); + } } From a0ab4e4e2b5cb4a1d602c22be0cf34dc1ea76265 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Fri, 1 Jun 2018 13:43:43 +0300 Subject: [PATCH 0897/2023] MAGETWO-90739: Out of stock options for configurable products still show up in search and layered navigation if Elasticsearch is enabled --- app/code/Magento/Elasticsearch/Model/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Elasticsearch/Model/Config.php b/app/code/Magento/Elasticsearch/Model/Config.php index 3d55979dfcee8..a0f3b6433b43b 100644 --- a/app/code/Magento/Elasticsearch/Model/Config.php +++ b/app/code/Magento/Elasticsearch/Model/Config.php @@ -67,7 +67,7 @@ class Config implements ClientOptionsInterface * @param ScopeConfigInterface $scopeConfig * @param ClientResolver|null $clientResolver * @param EngineResolverInterface|null $engineResolver - * @param string $prefix + * @param string|null $prefix */ public function __construct( ScopeConfigInterface $scopeConfig, From 1113749443782fec52f81e05bdffe25d05301de8 Mon Sep 17 00:00:00 2001 From: Daniel Ruf <daniel.ruf@ueberbit.de> Date: Fri, 18 May 2018 13:32:38 +0200 Subject: [PATCH 0898/2023] chore: remove extraneous cursor property --- lib/web/css/source/lib/_buttons.less | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/web/css/source/lib/_buttons.less b/lib/web/css/source/lib/_buttons.less index 804302fcb69ac..679c4b11fbaac 100644 --- a/lib/web/css/source/lib/_buttons.less +++ b/lib/web/css/source/lib/_buttons.less @@ -266,8 +266,7 @@ &.disabled, &[disabled], fieldset[disabled] & { - cursor: not-allowed; - pointer-events: none; // Disabling of clicks + pointer-events: none; // Disabling of all pointer events .lib-css(opacity, @button__disabled__opacity); } } From 9b1b80e8c69725d91d544003b82344fc6b0380c9 Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Fri, 1 Jun 2018 14:32:43 +0300 Subject: [PATCH 0899/2023] MAGETWO-90349: Template file 'header.html' is not found. --- app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php index 35d562fa7e5ec..973d342e7f597 100644 --- a/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php @@ -437,7 +437,7 @@ public function testGetDesignConfig() /** * @return void */ - public function testSetForcedAreaWhenAreIsSet(): void + public function testSetForcedAreaWhenAreaIsSet(): void { $templateId = 'test_template'; $model = $this->getModelMock([], ['area' => 'frontend']); From d696233736f0883e5c54f0ba81f635f8e2da8603 Mon Sep 17 00:00:00 2001 From: Ankur Raiyani <ankurvr7003@gmail.com> Date: Fri, 1 Jun 2018 17:28:53 +0530 Subject: [PATCH 0900/2023] Wrong Last orders amount on dashboard #15660 Wrong order amount on dashboard on Last orders listing when having more than one website with different currencies #15660 --- .../Backend/Block/Widget/Grid/Column/Renderer/Currency.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Currency.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Currency.php index ff0399e4f507f..b3f467ce37c88 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Currency.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Currency.php @@ -68,10 +68,7 @@ public function __construct( $this->_storeManager = $storeManager; $this->_currencyLocator = $currencyLocator; $this->_localeCurrency = $localeCurrency; - $defaultBaseCurrencyCode = $this->_scopeConfig->getValue( - \Magento\Directory\Model\Currency::XML_PATH_CURRENCY_BASE, - 'default' - ); + $defaultBaseCurrencyCode = $currencyLocator->getDefaultCurrency($this->_request); $this->_defaultBaseCurrency = $currencyFactory->create()->load($defaultBaseCurrencyCode); } From 45da02260c989f088b4645307e4af42d9b944b00 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Fri, 1 Jun 2018 15:53:13 +0300 Subject: [PATCH 0901/2023] MAGETWO-91807: Error when adding a product to the cart in the backend with the capitalization of the sku --- .../Catalog/Model/ProductRepository.php | 77 ++++++++++++++++--- .../Test/Unit/Model/ProductRepositoryTest.php | 27 ++++--- .../Catalog/Model/ProductRepositoryTest.php | 67 ++++++++++++++++ 3 files changed, 151 insertions(+), 20 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 6a82658342824..a75e5349baa30 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -233,7 +233,8 @@ public function __construct( public function get($sku, $editMode = false, $storeId = null, $forceReload = false) { $cacheKey = $this->getCacheKey([$editMode, $storeId]); - if (!isset($this->instances[$sku][$cacheKey]) || $forceReload) { + $cachedProduct = $this->getProductFromLocalCache($sku, $cacheKey); + if ($cachedProduct === null || $forceReload) { $product = $this->productFactory->create(); $productId = $this->resourceModel->getIdBySku($sku); @@ -250,11 +251,10 @@ public function get($sku, $editMode = false, $storeId = null, $forceReload = fal } $product->load($productId); $this->cacheProduct($cacheKey, $product); + $cachedProduct = $product; } - if (!isset($this->instances[$sku])) { - $sku = trim($sku); - } - return $this->instances[$sku][$cacheKey]; + + return $cachedProduct; } /** @@ -312,7 +312,7 @@ protected function getCacheKey($data) private function cacheProduct($cacheKey, \Magento\Catalog\Api\Data\ProductInterface $product) { $this->instancesById[$product->getId()][$cacheKey] = $product; - $this->instances[$product->getSku()][$cacheKey] = $product; + $this->saveProductInLocalCache($product, $cacheKey); if ($this->cacheLimit && count($this->instances) > $this->cacheLimit) { $offset = round($this->cacheLimit / -2); @@ -338,7 +338,7 @@ protected function initializeProductData(array $productData, $createNew) $product->setWebsiteIds([$this->storeManager->getStore(true)->getWebsiteId()]); } } else { - unset($this->instances[$productData['sku']]); + $this->removeProductFromLocalCache($productData['sku']); $product = $this->get($productData['sku']); } @@ -613,7 +613,7 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO if ($tierPrices !== null) { $product->setData('tier_price', $tierPrices); } - unset($this->instances[$product->getSku()]); + $this->removeProductFromLocalCache($product->getSku()); unset($this->instancesById[$product->getId()]); $this->resourceModel->save($product); } catch (ConnectionException $exception) { @@ -650,8 +650,9 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO $e ); } - unset($this->instances[$product->getSku()]); + $this->removeProductFromLocalCache($product->getSku()); unset($this->instancesById[$product->getId()]); + return $this->get($product->getSku(), false, $product->getStoreId()); } @@ -663,7 +664,7 @@ public function delete(\Magento\Catalog\Api\Data\ProductInterface $product) $sku = $product->getSku(); $productId = $product->getId(); try { - unset($this->instances[$product->getSku()]); + $this->removeProductFromLocalCache($product->getSku()); unset($this->instancesById[$product->getId()]); $this->resourceModel->delete($product); } catch (ValidatorException $e) { @@ -673,8 +674,9 @@ public function delete(\Magento\Catalog\Api\Data\ProductInterface $product) __('The "%1" product couldn\'t be removed.', $sku) ); } - unset($this->instances[$sku]); + $this->removeProductFromLocalCache($sku); unset($this->instancesById[$productId]); + return true; } @@ -796,4 +798,57 @@ private function getCollectionProcessor() } return $this->collectionProcessor; } + + /** + * Gets product from the local cache by SKU. + * + * @param string $sku + * @param string $cacheKey + * @return Product|null + */ + private function getProductFromLocalCache(string $sku, string $cacheKey) + { + $preparedSku = $this->prepareSku($sku); + if (!isset($this->instances[$preparedSku])) { + return null; + } + + return $this->instances[$preparedSku][$cacheKey] ?? null; + } + + /** + * Removes product in the local cache. + * + * @param string $sku + * @return void + */ + private function removeProductFromLocalCache(string $sku) :void + { + $preparedSku = $this->prepareSku($sku); + unset($this->instances[$preparedSku]); + } + + /** + * Saves product in the local cache. + * + * @param Product $product + * @param string $cacheKey + * @return void + */ + private function saveProductInLocalCache(Product $product, string $cacheKey) : void + { + $preparedSku = $this->prepareSku($product->getSku()); + $this->instances[$preparedSku][$cacheKey] = $product; + } + + /** + * Converts SKU to lower case and trims. + * + * @param string $sku + * @return string + */ + private function prepareSku(string $sku): string + { + return mb_strtolower(trim($sku)); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php index a370cbea13c2b..bf5c3d8276295 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php @@ -381,11 +381,11 @@ public function testGetByIdAbsentProduct() public function testGetByIdProductInEditMode() { $productId = 123; - $this->productFactoryMock->expects($this->once())->method('create') - ->will($this->returnValue($this->productMock)); - $this->productMock->expects($this->once())->method('setData')->with('_edit_mode', true); - $this->productMock->expects($this->once())->method('load')->with($productId); + $this->productFactoryMock->method('create')->willReturn($this->productMock); + $this->productMock->method('setData')->with('_edit_mode', true); + $this->productMock->method('load')->with($productId); $this->productMock->expects($this->atLeastOnce())->method('getId')->willReturn($productId); + $this->productMock->method('getSku')->willReturn('simple'); $this->assertEquals($this->productMock, $this->model->getById($productId, true)); } @@ -411,6 +411,7 @@ public function testGetByIdForCacheKeyGenerate($identifier, $editMode, $storeId) } $this->productMock->expects($this->once())->method('load')->with($identifier); $this->productMock->expects($this->atLeastOnce())->method('getId')->willReturn($identifier); + $this->productMock->method('getSku')->willReturn('simple'); $this->assertEquals($this->productMock, $this->model->getById($identifier, $editMode, $storeId)); //Second invocation should just return from cache $this->assertEquals($this->productMock, $this->model->getById($identifier, $editMode, $storeId)); @@ -433,6 +434,7 @@ public function testGetByIdForcedReload() $this->serializerMock->expects($this->exactly(3))->method('serialize'); $this->productMock->expects($this->exactly(4))->method('getId')->willReturn($identifier); + $this->productMock->method('getSku')->willReturn('simple'); $this->assertEquals($this->productMock, $this->model->getById($identifier, $editMode, $storeId)); //second invocation should just return from cache $this->assertEquals($this->productMock, $this->model->getById($identifier, $editMode, $storeId)); @@ -532,6 +534,7 @@ public function testGetByIdWithSetStoreId() $this->productMock->expects($this->once())->method('setData')->with('store_id', $storeId); $this->productMock->expects($this->once())->method('load')->with($productId); $this->productMock->expects($this->atLeastOnce())->method('getId')->willReturn($productId); + $this->productMock->method('getSku')->willReturn('simple'); $this->assertEquals($this->productMock, $this->model->getById($productId, false, $storeId)); } @@ -585,7 +588,8 @@ public function testSaveNew() ->expects($this->once()) ->method('toNestedArray') ->will($this->returnValue($this->productData)); - $this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([]); + $this->productMock->method('getWebsiteIds')->willReturn([]); + $this->productMock->method('getSku')->willReturn('simple'); $this->assertEquals($this->productMock, $this->model->save($this->productMock)); } @@ -597,7 +601,8 @@ public function testSaveNew() public function testSaveUnableToSaveException() { $this->storeManagerMock->expects($this->any())->method('getWebsites')->willReturn([1 => 'default']); - $this->resourceModelMock->expects($this->exactly(1))->method('getIdBySku')->will($this->returnValue(null)); + $this->resourceModelMock->expects($this->exactly(1)) + ->method('getIdBySku')->willReturn(null); $this->productFactoryMock->expects($this->exactly(2)) ->method('create') ->will($this->returnValue($this->productMock)); @@ -610,7 +615,8 @@ public function testSaveUnableToSaveException() ->expects($this->once()) ->method('toNestedArray') ->will($this->returnValue($this->productData)); - $this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([]); + $this->productMock->method('getWebsiteIds')->willReturn([]); + $this->productMock->method('getSku')->willReturn('simple'); $this->model->save($this->productMock); } @@ -637,6 +643,7 @@ public function testSaveException() ->method('toNestedArray') ->will($this->returnValue($this->productData)); $this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([]); + $this->productMock->method('getSku')->willReturn('simple'); $this->model->save($this->productMock); } @@ -661,6 +668,7 @@ public function testSaveInvalidProductException() ->method('toNestedArray') ->will($this->returnValue($this->productData)); $this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([]); + $this->productMock->method('getSku')->willReturn('simple'); $this->model->save($this->productMock); } @@ -692,6 +700,7 @@ public function testSaveThrowsTemporaryStateExceptionIfDatabaseConnectionErrorOc $this->productMock->expects($this->once()) ->method('getWebsiteIds') ->willReturn([]); + $this->productMock->method('getSku')->willReturn('simple'); $this->model->save($this->productMock); } @@ -734,9 +743,8 @@ public function testGetList() { $searchCriteriaMock = $this->createMock(\Magento\Framework\Api\SearchCriteriaInterface::class); $collectionMock = $this->createMock(\Magento\Catalog\Model\ResourceModel\Product\Collection::class); - $this->collectionFactoryMock->expects($this->once())->method('create')->willReturn($collectionMock); - + $this->productMock->method('getSku')->willReturn('simple'); $collectionMock->expects($this->once())->method('addAttributeToSelect')->with('*'); $collectionMock->expects($this->exactly(2))->method('joinAttribute')->withConsecutive( ['status', 'catalog_product/status', 'entity_id', null, 'inner'], @@ -1299,6 +1307,7 @@ public function testSaveWithDifferentWebsites() ]); $this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([1,2,3]); $this->productMock->expects($this->once())->method('setWebsiteIds')->willReturn([2,3]); + $this->productMock->method('getSku')->willReturn('simple'); $this->assertEquals($this->productMock, $this->model->save($this->productMock)); } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php new file mode 100644 index 0000000000000..d6ab99f2ca576 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Provide tests for ProductRepository model. + * + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ +class ProductRepositoryTest extends \PHPUnit\Framework\TestCase +{ + /** + * Test subject. + * + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->productRepository = Bootstrap::getObjectManager() + ->get(ProductRepositoryInterface::class); + } + + /** + * Check a case when product should be retrieved with different SKU variations. + * + * @param string $sku + * @return void + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @dataProvider skuDataProvider + */ + public function testGetProduct(string $sku) : void + { + $expectedSku = 'simple'; + $product = $this->productRepository->get($sku); + + self::assertNotEmpty($product); + self::assertEquals($expectedSku, $product->getSku()); + } + + /** + * Get list of SKU variations for the same product. + * + * @return array + */ + public function skuDataProvider(): array + { + return [ + ['sku' => 'simple'], + ['sku' => 'Simple'], + ['sku' => 'simple '], + ]; + } +} From c5eab1c0fc9e0eac46e0d0fc7466973badc5e1fa Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 1 Jun 2018 16:05:03 +0300 Subject: [PATCH 0902/2023] MAGETWO-90349: Template file 'header.html' is not found. --- .../Test/Unit/Model/AbstractTemplateTest.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php index 973d342e7f597..eeb7b5730dc93 100644 --- a/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php @@ -438,11 +438,27 @@ public function testGetDesignConfig() * @return void */ public function testSetForcedAreaWhenAreaIsSet(): void + { + $templateId = 'test_template'; + $model = $this->getModelMock([], ['area' => null]); + + $this->emailConfig->expects($this->once()) + ->method('getTemplateArea') + ->with($templateId); + + $model->setForcedArea($templateId); + } + + /** + * @return void + */ + public function testNotSetForcedAreaWhenAreaIsSet(): void { $templateId = 'test_template'; $model = $this->getModelMock([], ['area' => 'frontend']); - $this->emailConfig->expects($this->never())->method('getTemplateArea'); + $this->emailConfig->expects($this->never()) + ->method('getTemplateArea'); $model->setForcedArea($templateId); } From 662a316cda4f5e951f3b59cd770472d40286ae5f Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 1 Jun 2018 16:07:14 +0300 Subject: [PATCH 0903/2023] MAGETWO-90349: Template file 'header.html' is not found. --- .../Magento/Email/Test/Unit/Model/AbstractTemplateTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php index eeb7b5730dc93..4f545360616c6 100644 --- a/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/AbstractTemplateTest.php @@ -437,7 +437,7 @@ public function testGetDesignConfig() /** * @return void */ - public function testSetForcedAreaWhenAreaIsSet(): void + public function testSetForcedAreaWhenAreaIsNotSet(): void { $templateId = 'test_template'; $model = $this->getModelMock([], ['area' => null]); @@ -452,7 +452,7 @@ public function testSetForcedAreaWhenAreaIsSet(): void /** * @return void */ - public function testNotSetForcedAreaWhenAreaIsSet(): void + public function testSetForcedAreaWhenAreaIsSet(): void { $templateId = 'test_template'; $model = $this->getModelMock([], ['area' => 'frontend']); From cb24bdf7bfd48e55221f6de16690653a6b7918c5 Mon Sep 17 00:00:00 2001 From: Levi Villarreal <villarreallevi@gmail.com> Date: Fri, 1 Jun 2018 09:58:26 -0500 Subject: [PATCH 0904/2023] MC-234: Admin should be able to create category from the product page --- .../ActionGroup/AdminCategoryActionGroup.xml | 54 +++++++++++++++++++ .../AdminProductCategoryCreationSection.xml | 26 +++++++++ .../AdminCreateCategoryFromProductPage.xml | 44 +++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductCategoryCreationSection.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminCreateCategoryFromProductPage.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml index 96e40e348a6f2..006c7ff7beb7d 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AdminCategoryActionGroup.xml @@ -118,6 +118,60 @@ <dontSee selector="{{AdminCategorySidebarTreeSection.categoryInTree(categoryEntity.name)}}" stepKey="dontSeeCategoryInTree"/> </actionGroup> + <!-- Actions to fill out a new category from the product page--> + <actionGroup name="FillNewProductCategory" > + <arguments> + <argument name="categoryName" defaultValue="Test Category" type="string"/> + </arguments> + + <!--Navigate to product page --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> + <waitForPageLoad stepKey="waitForProductIndexPage"/> + + <!-- Click first example product --> + <click stepKey="clickFirstExampleProduct" selector="{{AdminProductCategoryCreationSection.firstExampleProduct}}" /> + <waitForPageLoad stepKey="waitForSpecificProductPage"/> + + <!-- Click on new Category --> + <click stepKey="clickNewCategory" selector="{{AdminProductCategoryCreationSection.newCategory}}" /> + <waitForPageLoad stepKey="waitForFieldSet"/> + + <fillField stepKey="fillCategoryName" selector="{{AdminProductCategoryCreationSection.nameInput}}" userInput="{{categoryName}}" /> + + <click stepKey="clickParentCategory" selector="{{AdminProductCategoryCreationSection.parentCategory}}" /> + <waitForPageLoad stepKey="waitForDropDownVisible"/> + + <click stepKey="clickDefaultParentCategory" selector="{{AdminProductCategoryCreationSection.parentCategoryDropdownDefaultOption}}" /> + + <click stepKey="createCategory" selector="{{AdminProductCategoryCreationSection.createCategory}}" /> + </actionGroup> + + <!-- Actions to delete the category last made --> + <actionGroup name="DeleteMostRecentCategory"> + <click stepKey="goToCreateCategory" selector="{{AdminProductCategoryCreationSection.lastCreatedCategory}}" /> + <waitForPageLoad stepKey="waitForCreatedCategoryPageLoad"/> + + <click stepKey="clickDeleteCategory" selector="{{AdminProductCategoryCreationSection.categoryDeleteButton}}" /> + <waitForPageLoad stepKey="waitForModalVisible"/> + + <click stepKey="clickOkToDelete" selector="{{AdminProductCategoryCreationSection.acceptDeletion}}" /> + + <waitForPageLoad stepKey="waitForModalNotVisible"/> + + </actionGroup> + + <!-- Actions to check if a certain category is present on the page --> + <actionGroup name="CategoryPresent" > + <arguments> + <argument name="categoryName" defaultValue="Test Category" type="string"/> + </arguments> + + <amOnPage url="{{AdminCategoryPage.url}}" stepKey="goToCategoryFrontPage"/> + <waitForPageLoad stepKey="waitForCategoryPageLoad"/> + + <see selector="{{AdminProductCategoryCreationSection.categoryStructure}}" userInput="{{categoryName}}" stepKey="assertCategoryOnStorefront"/> + </actionGroup> + <!--Check that name field is required--> <actionGroup name="CheckCategoryNameIsRequiredField"> <seeInCurrentUrl url="{{AdminCategoryPage.url}}" stepKey="seeOnCategoryPage"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductCategoryCreationSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductCategoryCreationSection.xml new file mode 100644 index 0000000000000..a983a7f24f803 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductCategoryCreationSection.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> + <section name="AdminProductCategoryCreationSection"> + <element name="firstExampleProduct" type="button" selector=".data-row:nth-of-type(1)" /> + <element name="newCategory" type="button" selector="//button/span[text()='New Category']" /> + + <element name="nameInput" type="input" selector="input[name='name']" /> + + <element name="parentCategory" type="block" selector=".product_form_product_form_create_category_modal div[data-role='selected-option']" /> + <element name="parentCategoryDropdownDefaultOption" type="block" selector=".product_form_product_form_create_category_modal .action-menu-item._expended .admin__action-multiselect-label" /> + <element name="createCategory" type="button" selector="#save" /> + + <element name="categoryStructure" type="button" selector="#ext-gen5" /> + <element name="lastCreatedCategory" type="block" selector=".x-tree-root-ct li li:last-child" /> + <element name="categoryDeleteButton" type="button" selector="//button/span[text()='Delete']" /> + <element name="acceptDeletion" type="button" selector="//button/span[text()='OK']" /> + </section> +</sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminCreateCategoryFromProductPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminCreateCategoryFromProductPage.xml new file mode 100644 index 0000000000000..7986f055cbb3c --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminCreateCategoryFromProductPage.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdminCreateCategoryFromProductPage"> + <annotations> + <features value="Category"/> + <stories value="Admin should be able to create category from the product page"/> + <description value="Admin should be able to create category from the product page" /> + <severity value="AVERAGE" /> + <testCaseId value="MC-234" /> + <group value="Catalog" /> + </annotations> + <before> + <createData entity="SimpleTwo" stepKey="simpleProduct"> + </createData> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + </after> + + <!-- Create new category in the product page with the category of AdminCreateCategoryFromProductPage --> + <actionGroup ref="FillNewProductCategory" stepKey="FillNewProductCategory"> + <argument name="categoryName" value="AdminCreateCategoryFromProductPage" /> + </actionGroup> + + <!-- Check that category was created --> + <actionGroup ref="CategoryPresent" stepKey="checkIfCategoryPresent"> + <argument name="categoryName" value="AdminCreateCategoryFromProductPage" /> + </actionGroup> + + <!-- Delete the created category --> + <actionGroup ref="DeleteMostRecentCategory" stepKey="getRidOfCreatedCategory" /> + + </test> +</tests> From d5c395295aa59d8d42e12dca82ec933bad096668 Mon Sep 17 00:00:00 2001 From: Sanjay Patel <sanjay@wagento.com> Date: Sat, 19 May 2018 11:23:56 +0530 Subject: [PATCH 0905/2023] #14063 - Wrong invoice prefix in multistore setup due to default store id --- .../Magento/Sales/Model/ResourceModel/EntityAbstract.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/ResourceModel/EntityAbstract.php b/app/code/Magento/Sales/Model/ResourceModel/EntityAbstract.php index 1b781890e0f7f..80612277e68d5 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/EntityAbstract.php +++ b/app/code/Magento/Sales/Model/ResourceModel/EntityAbstract.php @@ -123,10 +123,15 @@ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) { /** @var \Magento\Sales\Model\AbstractModel $object */ if ($object instanceof EntityInterface && $object->getIncrementId() == null) { + $store = $object->getStore(); + $storeId = $store->getId(); + if ($storeId === null) { + $storeId = $store->getGroup()->getDefaultStoreId(); + } $object->setIncrementId( $this->sequenceManager->getSequence( $object->getEntityType(), - $object->getStore()->getGroup()->getDefaultStoreId() + $storeId )->getNextValue() ); } From 2feaf3049e3b2397ba54aafcaa9ec5ff8cba0d83 Mon Sep 17 00:00:00 2001 From: Sanjay Patel <sanjay@wagento.com> Date: Wed, 30 May 2018 16:34:16 +0530 Subject: [PATCH 0906/2023] set correct annotation --- lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php | 4 ++-- .../Magento/Framework/Stdlib/DateTime/TimezoneInterface.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php index 9f182f3dc00a4..3c2f20fcc186f 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php @@ -260,8 +260,8 @@ public function isScopeDateInInterval($scope, $dateFrom = null, $dateTo = null) * @param string|\DateTimeInterface $date * @param int $dateType * @param int $timeType - * @param null $locale - * @param null $timezone + * @param string|null $locale + * @param string|null $timezone * @param string|null $pattern * @return string */ diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php b/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php index 047ca9d8b4528..a8b3fb1a81ffe 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php @@ -124,8 +124,8 @@ public function isScopeDateInInterval($scope, $dateFrom = null, $dateTo = null); * @param string|\DateTimeInterface $date * @param int $dateType * @param int $timeType - * @param null $locale - * @param null $timezone + * @param string|null $locale + * @param string|null $timezone * @param string|null $pattern * @return string */ From 11923bc4439e29bd707226bef8377f2ea458a29a Mon Sep 17 00:00:00 2001 From: Sanjay Patel <sanjay@wagento.com> Date: Sat, 19 May 2018 12:41:34 +0530 Subject: [PATCH 0907/2023] #12820 - Wrong annotation in _toOptionArray - magento/framework/Data/Collection/AbstractDb.php --- lib/internal/Magento/Framework/Data/Collection/AbstractDb.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 4feaf21d2b2e8..63ba6824e5ab9 100644 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -630,7 +630,7 @@ public function fetchItem() /** * Overridden to use _idFieldName by default. * - * @param null $valueField + * @param string|null $valueField * @param string $labelField * @param array $additional * @return array From bc58afb6fae35356d14467c75a894610b89ed95b Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@magento.com> Date: Tue, 29 May 2018 16:57:11 -0500 Subject: [PATCH 0908/2023] MC-235: Customer should only see cart price rule discount if condition subtotal equals or greater than --- .../Section/PriceRuleConditionsSection.xml | 4 + .../Test/StorefrontCartPriceRuleSubtotal.xml | 94 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleSubtotal.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/PriceRuleConditionsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/PriceRuleConditionsSection.xml index 39c6dd6b31968..93ed408ce7a0e 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/PriceRuleConditionsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Section/PriceRuleConditionsSection.xml @@ -16,5 +16,9 @@ <element name="treeRoot" type="text" selector=".x-tree-root-ct.x-tree-lines"/> <element name="lastTreeNode" type="text" selector=".x-tree-root-ct.x-tree-lines > div > li > ul > li:last-child div img.x-tree-elbow-end-plus"/> <element name="subcategory4level" type="text" selector=".x-tree-root-ct.x-tree-lines > div > li > ul > li > ul > li > ul > li > ul > li > div img.x-tree-elbow-end-plus"/> + + <element name="ruleParamLink" type="button" selector="//*[@id='conditions__{{var1}}__children']/li[{{var2}}]/span[{{var3}}]/a" parameterized="true"/> + <element name="operatorByIndex" type="input" selector="#conditions__{{var1}}--{{var2}}__operator" parameterized="true"/> + <element name="valueByIndex" type="input" selector="#conditions__{{var1}}--{{var2}}__value" parameterized="true"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleSubtotal.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleSubtotal.xml new file mode 100644 index 0000000000000..9a2ed3d3eabd0 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleSubtotal.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="StorefrontCartPriceRuleSubtotal"> + <annotations> + <features value="SalesRule"/> + <stories value="Create cart price rule"/> + <title value="Customer should only see cart price rule discount if condition subtotal equals or greater than"/> + <description value="Customer should only see cart price rule discount if condition subtotal equals or greater than"/> + <severity value="AVERAGE"/> + <testCaseId value="MC-235"/> + <group value="SalesRule"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + + <after> + <!-- Delete the cart price rule we made during the test --> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> + <argument name="ruleName" value="{{SimpleSalesRule.name}}"/> + </actionGroup> + <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + </after> + + <!-- Create the rule... --> + <!-- Fill basic Rule Information fields --> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForRulesPage"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{SimpleSalesRule.name}}" stepKey="fillRuleName"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Main Website" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="NOT LOGGED IN" stepKey="selectCustomerGroup"/> + <!-- Fill Conditions section --> + <click selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="expandConditions"/> + <!-- Scroll down to fix some flaky behavior... --> + <scrollTo selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="scrollToConditionsTab"/> + <click selector="{{PriceRuleConditionsSection.createNewRule}}" stepKey="clickNewRule"/> + <selectOption selector="{{PriceRuleConditionsSection.rulesDropdown}}" userInput="Subtotal" stepKey="selectProductAttributes"/> + <waitForPageLoad stepKey="waitForConditions"/> + <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '1')}}" stepKey="startEditOperator"/> + <selectOption selector="{{PriceRuleConditionsSection.operatorByIndex('1', '1')}}" userInput="equals or greater than" stepKey="fillOperator"/> + <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '2')}}" stepKey="startEditValue"/> + <fillField selector="{{PriceRuleConditionsSection.valueByIndex('1', '1')}}" userInput="200" stepKey="fillValue"/> + <!-- Fill Actions section --> + <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="Fixed amount discount for whole cart" stepKey="selectActionType"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="0.01" stepKey="fillDiscountAmount"/> + <!-- Save the rule --> + <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> + <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> + + <!-- Create a product to use in the storefront --> + <actionGroup ref="FillAdminSimpleProductForm" stepKey="fillProductFieldsInAdmin"> + <argument name="category" value="$$createPreReqCategory$$"/> + <argument name="simpleProduct" value="_defaultProduct"/> + </actionGroup> + + <!-- Add the product we created to our cart --> + <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + + <!-- Should not see the discount yet because we have not exceeded $200 --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> + <waitForPageLoad stepKey="waitForCartPage"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$123.00" stepKey="seeSubtotal"/> + <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount"/> + + <!-- Add another of the product to our cart --> + <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage2"/> + <waitForPageLoad stepKey="waitForProductPageLoad2"/> + <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity2"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart2"/> + + <!-- Now we should see the discount because we exceeded $200 --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage2"/> + <waitForPageLoad stepKey="waitForCartPage2"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$246.00" stepKey="seeSubtotal2"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$0.01" stepKey="seeDiscountTotal"/> + </test> +</tests> From 97561e2066592d9967e7c86c6ecace9474f3d1c2 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@magento.com> Date: Wed, 30 May 2018 15:19:57 -0500 Subject: [PATCH 0909/2023] MC-236: Customer should only see cart price rule discount if condition total items quantity greater than --- .../Test/StorefrontCartPriceRuleQuantity.xml | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleQuantity.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleQuantity.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleQuantity.xml new file mode 100644 index 0000000000000..2a3f20b49c962 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleQuantity.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="StorefrontCartPriceRuleQuantity"> + <annotations> + <features value="SalesRule"/> + <stories value="Create cart price rule"/> + <title value="Customer should only see cart price rule discount if condition total items quantity greater than"/> + <description value="Customer should only see cart price rule discount if condition total items quantity greater than"/> + <severity value="AVERAGE"/> + <testCaseId value="MC-236"/> + <group value="SalesRule"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + + <after> + <!-- Delete the cart price rule we made during the test --> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> + <argument name="ruleName" value="{{SimpleSalesRule.name}}"/> + </actionGroup> + <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + </after> + + <!-- Create the rule... --> + <!-- Fill basic Rule Information fields --> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForRulesPage"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{SimpleSalesRule.name}}" stepKey="fillRuleName"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Main Website" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="NOT LOGGED IN" stepKey="selectCustomerGroup"/> + <!-- Fill Conditions section --> + <click selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="expandConditions"/> + <!-- Scroll down to fix some flaky behavior... --> + <scrollTo selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="scrollToConditionsTab"/> + <waitForElementVisible selector="{{PriceRuleConditionsSection.createNewRule}}" stepKey="waitForNewRule"/> + <click selector="{{PriceRuleConditionsSection.createNewRule}}" stepKey="clickNewRule"/> + <selectOption selector="{{PriceRuleConditionsSection.rulesDropdown}}" userInput="Total Items Quantity" stepKey="selectProductAttributes"/> + <waitForPageLoad stepKey="waitForConditions"/> + <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '1')}}" stepKey="startEditOperator"/> + <selectOption selector="{{PriceRuleConditionsSection.operatorByIndex('1', '1')}}" userInput="greater than" stepKey="fillOperator"/> + <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '2')}}" stepKey="startEditValue"/> + <fillField selector="{{PriceRuleConditionsSection.valueByIndex('1', '1')}}" userInput="1" stepKey="fillValue"/> + <!-- Fill Actions section --> + <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="Fixed amount discount for whole cart" stepKey="selectActionType"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="1.00" stepKey="fillDiscountAmount"/> + <!-- Save the rule --> + <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> + <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> + + <!-- Create a product to use in the storefront --> + <actionGroup ref="FillAdminSimpleProductForm" stepKey="fillProductFieldsInAdmin"> + <argument name="category" value="$$createPreReqCategory$$"/> + <argument name="simpleProduct" value="_defaultProduct"/> + </actionGroup> + + <!-- Add the product we created to our cart --> + <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + + <!-- Should not see the discount yet because we have only 1 item in our cart --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> + <waitForPageLoad stepKey="waitForCartPage"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$123.00" stepKey="seeSubtotal"/> + <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount"/> + + <!-- Add another of the product to our cart --> + <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage2"/> + <waitForPageLoad stepKey="waitForProductPageLoad2"/> + <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity2"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart2"/> + + <!-- Now we should see the discount because we have more than 1 item --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage2"/> + <waitForPageLoad stepKey="waitForCartPage2"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$246.00" stepKey="seeSubtotal2"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$1.00" stepKey="seeDiscountTotal"/> + </test> +</tests> From 5076e11686d4a470f8e1a58120d407959bddf3e2 Mon Sep 17 00:00:00 2001 From: Danny Verkade - Cream <danny@cream.nl> Date: Wed, 9 May 2018 11:57:20 +0200 Subject: [PATCH 0910/2023] Forward port of 15097 to 2.3-develop branch. --- .../FillQuoteAddressIdInSalesOrderAddress.php | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Sales/Setup/Patch/Data/FillQuoteAddressIdInSalesOrderAddress.php b/app/code/Magento/Sales/Setup/Patch/Data/FillQuoteAddressIdInSalesOrderAddress.php index 0ad2245a6287e..d3e13334bb3f9 100644 --- a/app/code/Magento/Sales/Setup/Patch/Data/FillQuoteAddressIdInSalesOrderAddress.php +++ b/app/code/Magento/Sales/Setup/Patch/Data/FillQuoteAddressIdInSalesOrderAddress.php @@ -93,27 +93,27 @@ public function apply() public function fillQuoteAddressIdInSalesOrderAddress() { $addressCollection = $this->addressCollectionFactory->create(); + $addressCollection->addFieldToFilter('quote_address_id', ['null' => true]); + /** @var \Magento\Sales\Model\Order\Address $orderAddress */ foreach ($addressCollection as $orderAddress) { - if (!$orderAddress->getData('quote_address_id')) { - $orderId = $orderAddress->getParentId(); - $addressType = $orderAddress->getAddressType(); - - /** @var \Magento\Sales\Model\Order $order */ - $order = $this->orderFactory->create()->load($orderId); - $quoteId = $order->getQuoteId(); - $quote = $this->quoteFactory->create()->load($quoteId); - - if ($addressType == \Magento\Sales\Model\Order\Address::TYPE_SHIPPING) { - $quoteAddressId = $quote->getShippingAddress()->getId(); - $orderAddress->setData('quote_address_id', $quoteAddressId); - } elseif ($addressType == \Magento\Sales\Model\Order\Address::TYPE_BILLING) { - $quoteAddressId = $quote->getBillingAddress()->getId(); - $orderAddress->setData('quote_address_id', $quoteAddressId); - } - - $orderAddress->save(); + $orderId = $orderAddress->getParentId(); + $addressType = $orderAddress->getAddressType(); + + /** @var \Magento\Sales\Model\Order $order */ + $order = $this->orderFactory->create()->load($orderId); + $quoteId = $order->getQuoteId(); + $quote = $this->quoteFactory->create()->load($quoteId); + + if ($addressType == \Magento\Sales\Model\Order\Address::TYPE_SHIPPING) { + $quoteAddressId = $quote->getShippingAddress()->getId(); + $orderAddress->setData('quote_address_id', $quoteAddressId); + } elseif ($addressType == \Magento\Sales\Model\Order\Address::TYPE_BILLING) { + $quoteAddressId = $quote->getBillingAddress()->getId(); + $orderAddress->setData('quote_address_id', $quoteAddressId); } + + $orderAddress->save(); } } From e7705ffcb60fa28fbcc13adea530b6265953a4ae Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@magento.com> Date: Fri, 1 Jun 2018 13:52:51 -0500 Subject: [PATCH 0911/2023] MC-235: Customer should only see cart price rule discount if condition subtotal equals or greater than - Create products via api instead of ui --- .../Test/StorefrontCartPriceRuleQuantity.xml | 25 ++++++++----------- .../Test/StorefrontCartPriceRuleSubtotal.xml | 25 ++++++++----------- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleQuantity.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleQuantity.xml index 2a3f20b49c962..4c206776a676d 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleQuantity.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleQuantity.xml @@ -21,27 +21,28 @@ <before> <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + <createData entity="_defaultProduct" stepKey="createPreReqProduct"> + <requiredEntity createDataKey="createPreReqCategory"/> + </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <!-- Delete the cart price rule we made during the test --> <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> <argument name="ruleName" value="{{SimpleSalesRule.name}}"/> </actionGroup> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + <deleteData createDataKey="createPreReqProduct" stepKey="deletePreReqProduct"/> <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> </after> <!-- Create the rule... --> - <!-- Fill basic Rule Information fields --> <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> <waitForPageLoad stepKey="waitForRulesPage"/> <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{SimpleSalesRule.name}}" stepKey="fillRuleName"/> <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Main Website" stepKey="selectWebsites"/> <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="NOT LOGGED IN" stepKey="selectCustomerGroup"/> - <!-- Fill Conditions section --> <click selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="expandConditions"/> <!-- Scroll down to fix some flaky behavior... --> <scrollTo selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="scrollToConditionsTab"/> @@ -53,25 +54,18 @@ <selectOption selector="{{PriceRuleConditionsSection.operatorByIndex('1', '1')}}" userInput="greater than" stepKey="fillOperator"/> <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '2')}}" stepKey="startEditValue"/> <fillField selector="{{PriceRuleConditionsSection.valueByIndex('1', '1')}}" userInput="1" stepKey="fillValue"/> - <!-- Fill Actions section --> <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="Fixed amount discount for whole cart" stepKey="selectActionType"/> <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="1.00" stepKey="fillDiscountAmount"/> - <!-- Save the rule --> <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> - <!-- Create a product to use in the storefront --> - <actionGroup ref="FillAdminSimpleProductForm" stepKey="fillProductFieldsInAdmin"> - <argument name="category" value="$$createPreReqCategory$$"/> - <argument name="simpleProduct" value="_defaultProduct"/> - </actionGroup> - - <!-- Add the product we created to our cart --> - <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage"/> + <!-- Add 1 product to the cart --> + <amOnPage url="$$createPreReqProduct.name$$.html" stepKey="goToProductPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + <waitForPageLoad stepKey="waitForAddToCart"/> <!-- Should not see the discount yet because we have only 1 item in our cart --> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> @@ -79,11 +73,12 @@ <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$123.00" stepKey="seeSubtotal"/> <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount"/> - <!-- Add another of the product to our cart --> - <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage2"/> + <!-- Add the same product to the cart again (2 total) --> + <amOnPage url="$$createPreReqProduct.name$$.html" stepKey="goToProductPage2"/> <waitForPageLoad stepKey="waitForProductPageLoad2"/> <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity2"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart2"/> + <waitForPageLoad stepKey="waitForAddToCart2"/> <!-- Now we should see the discount because we have more than 1 item --> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage2"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleSubtotal.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleSubtotal.xml index 9a2ed3d3eabd0..0f3a1568d0fef 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleSubtotal.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleSubtotal.xml @@ -21,27 +21,28 @@ <before> <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + <createData entity="_defaultProduct" stepKey="createPreReqProduct"> + <requiredEntity createDataKey="createPreReqCategory"/> + </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <!-- Delete the cart price rule we made during the test --> <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> <argument name="ruleName" value="{{SimpleSalesRule.name}}"/> </actionGroup> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + <deleteData createDataKey="createPreReqProduct" stepKey="deletePreReqProduct"/> <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> </after> <!-- Create the rule... --> - <!-- Fill basic Rule Information fields --> <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> <waitForPageLoad stepKey="waitForRulesPage"/> <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{SimpleSalesRule.name}}" stepKey="fillRuleName"/> <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Main Website" stepKey="selectWebsites"/> <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="NOT LOGGED IN" stepKey="selectCustomerGroup"/> - <!-- Fill Conditions section --> <click selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="expandConditions"/> <!-- Scroll down to fix some flaky behavior... --> <scrollTo selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="scrollToConditionsTab"/> @@ -52,25 +53,18 @@ <selectOption selector="{{PriceRuleConditionsSection.operatorByIndex('1', '1')}}" userInput="equals or greater than" stepKey="fillOperator"/> <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '2')}}" stepKey="startEditValue"/> <fillField selector="{{PriceRuleConditionsSection.valueByIndex('1', '1')}}" userInput="200" stepKey="fillValue"/> - <!-- Fill Actions section --> <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="Fixed amount discount for whole cart" stepKey="selectActionType"/> <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="0.01" stepKey="fillDiscountAmount"/> - <!-- Save the rule --> <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> - <!-- Create a product to use in the storefront --> - <actionGroup ref="FillAdminSimpleProductForm" stepKey="fillProductFieldsInAdmin"> - <argument name="category" value="$$createPreReqCategory$$"/> - <argument name="simpleProduct" value="_defaultProduct"/> - </actionGroup> - - <!-- Add the product we created to our cart --> - <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage"/> + <!-- Add 1 product worth $123.00 to the cart --> + <amOnPage url="$$createPreReqProduct.name$$.html" stepKey="goToProductPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + <waitForPageLoad stepKey="waitForAddToCart"/> <!-- Should not see the discount yet because we have not exceeded $200 --> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> @@ -78,11 +72,12 @@ <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$123.00" stepKey="seeSubtotal"/> <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount"/> - <!-- Add another of the product to our cart --> - <amOnPage url="{{_defaultProduct.urlKey}}.html" stepKey="goToProductPage2"/> + <!-- Add the same product to the cart again ($246.00 subtotal) --> + <amOnPage url="$$createPreReqProduct.name$$.html" stepKey="goToProductPage2"/> <waitForPageLoad stepKey="waitForProductPageLoad2"/> <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity2"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart2"/> + <waitForPageLoad stepKey="waitForAddToCart2"/> <!-- Now we should see the discount because we exceeded $200 --> <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage2"/> From 080dba193c1ca8f7e3e17a8dea35fd5e0344dbc7 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 1 Jun 2018 15:34:47 -0500 Subject: [PATCH 0912/2023] MAGETWO-91434: Default option for 'Status' attribute not being set --- .../Product/Form/Modifier/GeneralTest.php | 89 ++++++++++++++++++- .../Product/Form/Modifier/General.php | 20 ++++- 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php index b4460b314513b..78502ae297b52 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/GeneralTest.php @@ -5,8 +5,11 @@ */ namespace Magento\Catalog\Test\Unit\Ui\DataProvider\Product\Form\Modifier; -use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Api\Data\ProductAttributeInterface; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\General; +use Magento\Eav\Api\AttributeRepositoryInterface; +use Magento\Eav\Api\Data\AttributeInterface; +use Magento\Framework\Stdlib\ArrayManager; /** * Class GeneralTest @@ -15,6 +18,35 @@ */ class GeneralTest extends AbstractModifierTest { + /** + * @var AttributeRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $attributeRepositoryMock; + + /** + * @var General + */ + private $generalModifier; + + protected function setUp() + { + parent::setUp(); + + $this->attributeRepositoryMock = $this->getMockBuilder(AttributeRepositoryInterface::class) + ->getMockForAbstractClass(); + + $arrayManager = $this->objectManager->getObject(ArrayManager::class); + + $this->generalModifier = $this->objectManager->getObject( + General::class, + [ + 'attributeRepository' => $this->attributeRepositoryMock, + 'locator' => $this->locatorMock, + 'arrayManager' => $arrayManager, + ] + ); + } + /** * {@inheritdoc} */ @@ -40,4 +72,59 @@ public function testModifyMeta() ] ])); } + + /** + * @param array $data + * @param int $defaultStatusValue + * @param array $expectedResult + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @dataProvider modifyDataDataProvider + */ + public function testModifyDataNewProduct(array $data, int $defaultStatusValue, array $expectedResult) + { + $attributeMock = $this->getMockBuilder(AttributeInterface::class) + ->getMockForAbstractClass(); + $attributeMock + ->method('getDefaultValue') + ->willReturn($defaultStatusValue); + $this->attributeRepositoryMock + ->method('get') + ->with( + ProductAttributeInterface::ENTITY_TYPE_CODE, + ProductAttributeInterface::CODE_STATUS + ) + ->willReturn($attributeMock); + $this->assertSame($expectedResult, $this->generalModifier->modifyData($data)); + } + + /** + * @return array + */ + public function modifyDataDataProvider(): array + { + return [ + 'With default status value' => [ + 'data' => [], + 'defaultStatusAttributeValue' => 5, + 'expectedResult' => [ + null => [ + General::DATA_SOURCE_DEFAULT => [ + ProductAttributeInterface::CODE_STATUS => 5, + ], + ], + ], + ], + 'Without default status value' => [ + 'data' => [], + 'defaultStatusAttributeValue' => 0, + 'expectedResult' => [ + null => [ + General::DATA_SOURCE_DEFAULT => [ + ProductAttributeInterface::CODE_STATUS => 1, + ], + ], + ], + ], + ]; + } } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php index ea69ebf4dda24..03d4dde311491 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php @@ -7,6 +7,7 @@ use Magento\Catalog\Api\Data\ProductAttributeInterface; use Magento\Catalog\Model\Locator\LocatorInterface; +use Magento\Eav\Api\AttributeRepositoryInterface; use Magento\Ui\Component\Form; use Magento\Framework\Stdlib\ArrayManager; @@ -35,21 +36,31 @@ class General extends AbstractModifier */ private $localeCurrency; + /** + * @var AttributeRepositoryInterface + */ + private $attributeRepository; + /** * @param LocatorInterface $locator * @param ArrayManager $arrayManager + * @param AttributeRepositoryInterface|null $attributeRepository */ public function __construct( LocatorInterface $locator, - ArrayManager $arrayManager + ArrayManager $arrayManager, + AttributeRepositoryInterface $attributeRepository = null ) { $this->locator = $locator; $this->arrayManager = $arrayManager; + $this->attributeRepository = $attributeRepository + ?: \Magento\Framework\App\ObjectManager::getInstance()->get(AttributeRepositoryInterface::class); } /** * {@inheritdoc} * @since 101.0.0 + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function modifyData(array $data) { @@ -58,7 +69,12 @@ public function modifyData(array $data) $modelId = $this->locator->getProduct()->getId(); if (!isset($data[$modelId][static::DATA_SOURCE_DEFAULT][ProductAttributeInterface::CODE_STATUS])) { - $data[$modelId][static::DATA_SOURCE_DEFAULT][ProductAttributeInterface::CODE_STATUS] = '1'; + $attributeStatus = $this->attributeRepository->get( + ProductAttributeInterface::ENTITY_TYPE_CODE, + ProductAttributeInterface::CODE_STATUS + ); + $data[$modelId][static::DATA_SOURCE_DEFAULT][ProductAttributeInterface::CODE_STATUS] = + $attributeStatus->getDefaultValue() ?: 1; } return $data; From b8773b58b9b73b9badc4b637b9e13cc53d162988 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@magento.com> Date: Fri, 1 Jun 2018 16:09:47 -0500 Subject: [PATCH 0913/2023] MC-238: Customer should only see cart price rule discount if condition shipping postcode --- .../Section/CheckoutCartSummarySection.xml | 2 + .../Test/StorefrontCartPriceRulePostcode.xml | 92 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRulePostcode.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml index 32a57a14cd9da..31dd20e74ebc3 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml @@ -15,5 +15,7 @@ <element name="total" type="text" selector="//*[@id='cart-totals']//tr[@class='grand totals']//td//span[@class='price']"/> <element name="proceedToCheckout" type="button" selector=".action.primary.checkout span" timeout="30"/> <element name="discountAmount" type="text" selector="td[data-th='Discount']"/> + <element name="shippingHeading" type="button" selector="#block-shipping-heading"/> + <element name="postcode" type="input" selector="input[name='postcode']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRulePostcode.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRulePostcode.xml new file mode 100644 index 0000000000000..1d8aba54f3675 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRulePostcode.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="StorefrontCartPriceRulePostcode"> + <annotations> + <features value="SalesRule"/> + <stories value="Create cart price rule"/> + <title value="Customer should only see cart price rule discount if condition shipping postcode"/> + <description value="Customer should only see cart price rule discount if condition shipping postcode"/> + <severity value="AVERAGE"/> + <testCaseId value="MC-238"/> + <group value="SalesRule"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + <createData entity="_defaultProduct" stepKey="createPreReqProduct"> + <requiredEntity createDataKey="createPreReqCategory"/> + </createData> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + + <after> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> + <argument name="ruleName" value="{{SimpleSalesRule.name}}"/> + </actionGroup> + <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + <deleteData createDataKey="createPreReqProduct" stepKey="deletePreReqProduct"/> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + </after> + + <!-- Create the rule... --> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForRulesPage"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{SimpleSalesRule.name}}" stepKey="fillRuleName"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Main Website" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="NOT LOGGED IN" stepKey="selectCustomerGroup"/> + <click selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="expandConditions"/> + <!-- Scroll down to fix some flaky behavior... --> + <scrollTo selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="scrollToConditionsTab"/> + <waitForElementVisible selector="{{PriceRuleConditionsSection.createNewRule}}" stepKey="waitForNewRule"/> + <click selector="{{PriceRuleConditionsSection.createNewRule}}" stepKey="clickNewRule"/> + <selectOption selector="{{PriceRuleConditionsSection.rulesDropdown}}" userInput="Shipping Postcode" stepKey="selectProductAttributes"/> + <waitForPageLoad stepKey="wait1"/> + <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '1')}}" stepKey="startEditOperator"/> + <waitForPageLoad stepKey="wait2"/> + <selectOption selector="{{PriceRuleConditionsSection.operatorByIndex('1', '1')}}" userInput="is one of" stepKey="fillOperator"/> + <waitForPageLoad stepKey="wait3"/> + <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '2')}}" stepKey="startEditValue"/> + <waitForPageLoad stepKey="wait4"/> + <fillField selector="{{PriceRuleConditionsSection.valueByIndex('1', '1')}}" userInput="78613" stepKey="fillValue"/> + <waitForPageLoad stepKey="wait5"/> + <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="Fixed amount discount for whole cart" stepKey="selectActionType"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="9.99" stepKey="fillDiscountAmount"/> + <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> + <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> + + <!-- Add the product we created to our cart --> + <amOnPage url="$$createPreReqProduct.name$$.html" stepKey="goToProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + <waitForPageLoad stepKey="waitForAddToCart"/> + + <!-- Should not see the discount yet because we have not filled in postcode --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> + <waitForPageLoad stepKey="waitForCartPage"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$123.00" stepKey="seeSubtotal"/> + <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount"/> + + <!-- See discount if we use valid postcode --> + <click selector="{{CheckoutCartSummarySection.shippingHeading}}" stepKey="expandShipping"/> + <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="78613" stepKey="fillPostcode"/> + <waitForPageLoad stepKey="waitForPostcode1"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$9.99" stepKey="seeDiscountTotal"/> + + <!-- Do not see discount with other postcode --> + <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="90210" stepKey="fillPostcode2"/> + <waitForPageLoad stepKey="waitForPostcode2"/> + <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount2"/> + </test> +</tests> From d4464646eb3021d4375eab61cfb490dadad5454c Mon Sep 17 00:00:00 2001 From: Nathan Smith <nathanjosiah@gmail.com> Date: Fri, 1 Jun 2018 16:44:18 -0500 Subject: [PATCH 0914/2023] MAGETWO-92021: Improving dev experience for Products content type - updated regex to allow dot separators in keys --- .../view/adminhtml/web/conditions-data-normalizer.js | 6 +++--- .../adminhtml/web/conditions-data-normalizer.test.js | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Rule/view/adminhtml/web/conditions-data-normalizer.js b/app/code/Magento/Rule/view/adminhtml/web/conditions-data-normalizer.js index c9c36c4fa585a..8eebc9ef0bd40 100644 --- a/app/code/Magento/Rule/view/adminhtml/web/conditions-data-normalizer.js +++ b/app/code/Magento/Rule/view/adminhtml/web/conditions-data-normalizer.js @@ -14,11 +14,11 @@ define([ */ var ConditionsDataNormalizer = function () { this.patterns = { - validate: /^[a-z0-9_-][a-z0-9_-]*(?:\[(?:\d*|[a-z0-9_-]+)\])*$/i, - key: /[a-z0-9_-]+|(?=\[\])/gi, + validate: /^[a-z0-9_.-][a-z0-9_.-]*(?:\[(?:\d*|[a-z0-9_.-]+)\])*$/i, + key: /[a-z0-9_.-]+|(?=\[\])/gi, push: /^$/, fixed: /^\d+$/, - named: /^[a-z0-9_-]+$/i + named: /^[a-z0-9_.-]+$/i }; }; diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Rule/view/adminhtml/web/conditions-data-normalizer.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Rule/view/adminhtml/web/conditions-data-normalizer.test.js index 21c04d098ae6c..ec820e537789a 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Rule/view/adminhtml/web/conditions-data-normalizer.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Rule/view/adminhtml/web/conditions-data-normalizer.test.js @@ -65,5 +65,17 @@ define([ expect(normal.foo['1'].value).toEqual(123); expect(normal.foo['1--1']).toEqual(321); }); + + it('Check keys containing a dot are normalized', function () { + var normal = normalizer.normalize({ + 'foo[1][name.foo]': 'bar', + 'foo[1][value.foo]': 123, + 'foo[1--1]': 321 + }); + + expect(normal.foo['1']['name.foo']).toEqual('bar'); + expect(normal.foo['1']['value.foo']).toEqual(123); + expect(normal.foo['1--1']).toEqual(321); + }); }); }); From b108cc8fa26f6ace43350cab1f7e52fa73d3ff63 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@magento.com> Date: Fri, 1 Jun 2018 16:50:41 -0500 Subject: [PATCH 0915/2023] MC-239: Customer should only see cart price rule discount if condition shipping state/province --- .../Section/CheckoutCartSummarySection.xml | 1 + .../Test/StorefrontCartPriceRuleState.xml | 89 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleState.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml index 31dd20e74ebc3..27d23143aff9d 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml @@ -17,5 +17,6 @@ <element name="discountAmount" type="text" selector="td[data-th='Discount']"/> <element name="shippingHeading" type="button" selector="#block-shipping-heading"/> <element name="postcode" type="input" selector="input[name='postcode']"/> + <element name="stateProvince" type="select" selector="select[name='region_id']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleState.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleState.xml new file mode 100644 index 0000000000000..a5c4a18591f31 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleState.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="StorefrontCartPriceRuleState"> + <annotations> + <features value="SalesRule"/> + <stories value="Create cart price rule"/> + <title value=""/> + <description value=""/> + <severity value="AVERAGE"/> + <testCaseId value="MC-239"/> + <group value="SalesRule"/> + <group value="banana"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + <createData entity="_defaultProduct" stepKey="createPreReqProduct"> + <requiredEntity createDataKey="createPreReqCategory"/> + </createData> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + + <after> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> + <argument name="ruleName" value="{{SimpleSalesRule.name}}"/> + </actionGroup> + <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + <deleteData createDataKey="createPreReqProduct" stepKey="deletePreReqProduct"/> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + </after> + + <!-- Create the rule... --> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForRulesPage"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{SimpleSalesRule.name}}" stepKey="fillRuleName"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Main Website" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="NOT LOGGED IN" stepKey="selectCustomerGroup"/> + <click selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="expandConditions"/> + <!-- Scroll down to fix some flaky behavior... --> + <scrollTo selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="scrollToConditionsTab"/> + <waitForElementVisible selector="{{PriceRuleConditionsSection.createNewRule}}" stepKey="waitForNewRule"/> + <click selector="{{PriceRuleConditionsSection.createNewRule}}" stepKey="clickNewRule"/> + <selectOption selector="{{PriceRuleConditionsSection.rulesDropdown}}" userInput="Shipping State/Province" stepKey="selectProductAttributes"/> + <waitForPageLoad stepKey="wait1"/> + <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '2')}}" stepKey="startEditValue"/> + <waitForPageLoad stepKey="wait2"/> + <selectOption selector="{{PriceRuleConditionsSection.valueByIndex('1', '1')}}" userInput="Indiana" stepKey="fillValue"/> + <waitForPageLoad stepKey="wait3"/> + <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="Fixed amount discount for whole cart" stepKey="selectActionType"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="9.99" stepKey="fillDiscountAmount"/> + <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> + <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> + + <!-- Add the product we created to our cart --> + <amOnPage url="$$createPreReqProduct.name$$.html" stepKey="goToProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + <waitForPageLoad stepKey="waitForAddToCart"/> + + <!-- Should not see the discount yet because we have not filled in postcode --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> + <waitForPageLoad stepKey="waitForCartPage"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$123.00" stepKey="seeSubtotal"/> + <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount"/> + + <!-- See discount if we use valid postcode --> + <click selector="{{CheckoutCartSummarySection.shippingHeading}}" stepKey="expandShipping"/> + <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="Indiana" stepKey="fillState"/> + <waitForPageLoad stepKey="waitForPostcode1"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$9.99" stepKey="seeDiscountTotal"/> + + <!-- Do not see discount with other postcode --> + <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="Texas" stepKey="fillState2"/> + <waitForPageLoad stepKey="waitForPostcode2"/> + <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount2"/> + </test> +</tests> From 760e889a5ecca1a2c87ea6119914df4802327b1b Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@magento.com> Date: Sun, 27 May 2018 14:34:14 -0500 Subject: [PATCH 0916/2023] MAGETWO-92247: Verify that product price is displayed on additional storefront if product is disabled for default store view --- .../Section/AdminProductFormSection.xml | 8 + .../ConfigWebUrlOptionsActionGroup.xml | 32 +++ .../Config/Section/GeneralSection.xml | 6 + .../Data/ProductConfigurableAttributeData.xml | 13 ++ ...reateProductConfigurationsPanelSection.xml | 2 + .../AdminProductFormConfigurationsSection.xml | 4 +- ...bleProductPriceAdditionalStoreViewTest.xml | 205 ++++++++++++++++++ .../AdminCreateNewStoreGroupActionGroup.xml | 23 ++ .../AdminCreateWebsiteActionGroup.xml | 21 ++ .../AdminDeleteWebsiteActionGroup.xml | 24 ++ .../Store/Page/AdminSystemStoreGroupPage.xml | 12 + .../Page/AdminSystemStoreWebsitePage.xml | 12 + .../Section/AdminNewStoreGroupSection.xml | 2 +- .../Section/AdminNewWebsiteActionsSection.xml | 12 + 14 files changed, 374 insertions(+), 2 deletions(-) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/ActionGroup/ConfigWebUrlOptionsActionGroup.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminCreateNewStoreGroupActionGroup.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminCreateWebsiteActionGroup.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminDeleteWebsiteActionGroup.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Page/AdminSystemStoreGroupPage.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Page/AdminSystemStoreWebsitePage.xml create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewWebsiteActionsSection.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductFormSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductFormSection.xml index 926d87e889931..a35fd3cf04479 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductFormSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductFormSection.xml @@ -10,6 +10,9 @@ <section name="AdminProductFormSection"> <element name="productName" type="input" selector=".admin__field[data-index=name] input"/> <element name="productSku" type="input" selector=".admin__field[data-index=sku] input"/> + <element name="enableProduct" type="checkbox" selector="input[name='product[status]']"/> + <element name="enableProductLabel" type="checkbox" selector="input[name='product[status]']+label"/> + <element name="productStatusUseDefault" type="checkbox" selector="input[name='use_default[status]']"/> <element name="productPrice" type="input" selector=".admin__field[data-index=price] input"/> <element name="advancedPricingLink" type="button" selector="button[data-index='advanced_pricing_button']"/> <element name="categoriesDropdown" type="multiselect" selector="div[data-index='category_ids']"/> @@ -31,6 +34,11 @@ <element name="visibility" type="select" selector="//select[@name='product[visibility]']"/> <element name="visibilityUseDefault" type="checkbox" selector="//input[@name='use_default[visibility]']"/> </section> + <section name="ProductInWebsitesSection"> + <element name="sectionHeader" type="button" selector="div[data-index='websites']" timeout="30"/> + <!--<element name="websites" type="checkbox" selector="input[name='product[website_ids][{{var1}}]']" parameterized="true"/>--> + <element name="website" type="checkbox" selector="//label[contains(text(), '{{var1}}')]/parent::div//input[@type='checkbox']" parameterized="true"/> + </section> <section name="ProductDesignSection"> <element name="DesignTab" type="button" selector="//strong[@class='admin__collapsible-title']//span[text()='Design']"/> <element name="LayoutDropdown" type="select" selector="select[name='product[page_layout]']"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/ActionGroup/ConfigWebUrlOptionsActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/ActionGroup/ConfigWebUrlOptionsActionGroup.xml new file mode 100644 index 0000000000000..56c313688fdb6 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/ActionGroup/ConfigWebUrlOptionsActionGroup.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="EnableWebUrlOptions"> + <amOnPage url="{{WebConfigurationPage.url}}" stepKey="navigateToWebConfigurationPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <conditionalClick selector="{{WebSection.UrlOptionsTab}}" dependentSelector="{{WebSection.CheckIfUrlOptionsTabExpand}}" visible="true" stepKey="expandUrlSectionTab"/> + <waitForElementVisible selector="{{UrlOptionsSection.addStoreCodeToUrl}}" stepKey="seeAddStoreCodeToUrl"/> + <uncheckOption selector="{{UrlOptionsSection.systemValueForStoreCode}}" stepKey="uncheckUseSystemValue"/> + <selectOption selector="{{UrlOptionsSection.addStoreCodeToUrl}}" userInput="Yes" stepKey="enableStoreCode"/> + <click selector="{{WebSection.UrlOptionsTab}}" stepKey="collapseUrlOptions"/> + <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfig" /> + </actionGroup> + <actionGroup name="ResetWebUrlOptions"> + <amOnPage url="{{WebConfigurationPage.url}}" stepKey="navigateToWebConfigurationPagetoReset"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <conditionalClick selector="{{WebSection.UrlOptionsTab}}" dependentSelector="{{WebSection.CheckIfUrlOptionsTabExpand}}" visible="true" stepKey="closeUrlSectionTab"/> + <waitForElementVisible selector="{{UrlOptionsSection.addStoreCodeToUrl}}" stepKey="seeAddStoreCodeToUrl2"/> + <!--<uncheckOption selector="{{UrlOptionsSection.systemValueForStoreCode}}" stepKey="uncheckUseSystemValue"/>--> + <selectOption selector="{{UrlOptionsSection.addStoreCodeToUrl}}" userInput="No" stepKey="enableStoreCode"/> + <checkOption selector="{{UrlOptionsSection.systemValueForStoreCode}}" stepKey="checkUseSystemValue"/> + <click selector="{{WebSection.UrlOptionsTab}}" stepKey="collapseUrlOptions"/> + <click selector="{{ContentManagementSection.Save}}" stepKey="saveConfig"/> + </actionGroup> +</actionGroups> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Section/GeneralSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Section/GeneralSection.xml index a8025085204bd..b51cfc1d316e5 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Section/GeneralSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Config/Section/GeneralSection.xml @@ -20,10 +20,16 @@ <section name="WebSection"> <element name="DefaultLayoutsTab" type="button" selector="#web_default_layouts-head"/> <element name="CheckIfTabExpand" type="button" selector="#web_default_layouts-head:not(.open)"/> + <element name="UrlOptionsTab" type="button" selector="#web_url-head"/> + <element name="CheckIfUrlOptionsTabExpand" type="button" selector="#web_url-head:not(.open)"/> </section> <section name="DefaultLayoutsSection"> <element name="productLayout" type="select" selector="#web_default_layouts_default_product_layout"/> <element name="categoryLayout" type="select" selector="#web_default_layouts_default_category_layout"/> <element name="pageLayout" type="select" selector="#web_default_layouts_default_cms_layout"/> </section> + <section name="UrlOptionsSection"> + <element name="addStoreCodeToUrl" type="select" selector="#web_url_use_store"/> + <element name="systemValueForStoreCode" type="checkbox" selector="#web_url_use_store_inherit"/> + </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Data/ProductConfigurableAttributeData.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Data/ProductConfigurableAttributeData.xml index 5a1c0139d56ca..ed8bbc949c550 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Data/ProductConfigurableAttributeData.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Data/ProductConfigurableAttributeData.xml @@ -29,4 +29,17 @@ <data key="name" unique="suffix">Orange</data> <data key="price">99.99</data> </entity> + <entity name="colorDefaultProductAttribute" type="product_attribute"> + <data key="default_label">Color</data> + <data key="input_type">Dropdown</data> + <data key="attribute_quantity">2</data> + </entity> + <entity name="colorDefaultProductAttribute1" type="product_attribute"> + <data key="name">Green</data> + <data key="price">4.00</data> + </entity> + <entity name="colorDefaultProductAttribute2" type="product_attribute"> + <data key="name">Black</data> + <data key="price">5.00</data> + </entity> </entities> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminCreateProductConfigurationsPanelSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminCreateProductConfigurationsPanelSection.xml index a097dfa4ad764..99f6a8842481e 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminCreateProductConfigurationsPanelSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminCreateProductConfigurationsPanelSection.xml @@ -24,6 +24,8 @@ <element name="attributeCheckboxByIndex" type="input" selector="li.attribute-option:nth-of-type({{var1}}) input" parameterized="true"/> <element name="applyUniquePricesByAttributeToEachSku" type="radio" selector=".admin__field-label[for='apply-unique-prices-radio']"/> + <element name="applySinglePriceToAllSkus" type="radio" selector=".admin__field-label[for='apply-single-price-radio']"/> + <element name="singlePrice" type="input" selector="#apply-single-price-input"/> <element name="selectAttribute" type="select" selector="#select-each-price" timeout="30"/> <element name="attribute1" type="input" selector="#apply-single-price-input-0"/> <element name="attribute2" type="input" selector="#apply-single-price-input-1"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminProductFormConfigurationsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminProductFormConfigurationsSection.xml index 40d700fd4b75c..43bf9822903be 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminProductFormConfigurationsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Section/AdminProductFormConfigurationsSection.xml @@ -16,14 +16,16 @@ <element name="currentVariationsPriceCells" type="textarea" selector=".admin__control-fields[data-index='price_container']"/> <element name="currentVariationsQuantityCells" type="textarea" selector=".admin__control-fields[data-index='quantity_container']"/> <element name="currentVariationsAttributesCells" type="textarea" selector=".admin__control-fields[data-index='attributes']"/> + <element name="currentVariationsStatusCells" type="textarea" selector="._no-header[data-index='status']"/> <element name="actionsBtn" type="button" selector="(//button[@class='action-select']/span[contains(text(), 'Select')])[{{var1}}]" parameterized="true"/> <element name="removeProductBtn" type="button" selector="//a[text()='Remove Product']"/> <element name="disableProductBtn" type="button" selector="//a[text()='Disable Product']"/> + <element name="enableProductBtn" type="button" selector="//a[text()='Enable Product']"/> </section> <section name="AdminConfigurableProductFormSection"> <element name="productWeight" type="input" selector=".admin__control-text[name='product[weight]']"/> <element name="productQuantity" type="input" selector=".admin__control-text[name='product[quantity_and_stock_status][qty]']"/> - <element name="currentVariationsQuantityCells" type="button" selector="td[data-index='quantity_per_source_container']"/> + <element name="currentVariationsQuantityCells" type="button" selector="td[data-index='quantity_container']"/> <element name="rowByCode" type="textarea" selector="//span[contains(text(), '{{var1}}-{{var2}}')]//ancestor-or-self::tr" parameterized="true"/> </section> <section name="AdminConfigurableProductSelectAttributesSlideOut"> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml new file mode 100644 index 0000000000000..56a9020c3a14d --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="ConfigurableProductPriceAdditionalStoreViewTest"> + <annotations> + <features value="ConfigurableProductPriceStoreFront"/> + <title value="Configurable product prices should not disappear on storefront for additional store"/> + <description value="Configurable product price should not disappear for additional stores on frontEnd if disabled for default store"/> + <severity value="CRITICAL"/> + <testCaseId value="MAGETWO-92247"/> + <group value="configurable"/> + <group value="product"/> + </annotations> + <before> + + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct2"/> + </createData> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> + </before> + + <after> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <actionGroup ref="ResetWebUrlOptions" stepKey="resetUrlOption"/> + <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"/> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + </after> + + <actionGroup ref="EnableWebUrlOptions" stepKey="addStoreCodeToUrls"/> + <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="addnewWebsite"/> + <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="addNewStoreGroup"/> + + <!--Create Store view --> + <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="amOnAdminSystemStorePage"/> + <click selector="{{AdminStoresMainActionsSection.createStoreViewButton}}" stepKey="createStoreViewButton"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <selectOption userInput="Second Store" selector="{{AdminNewStoreSection.storeGrpDropdown}}" stepKey="selectStoreGroup"/> + <fillField userInput="Second Store View" selector="{{AdminNewStoreSection.storeNameTextField}}" stepKey="fillStoreViewName"/> + <fillField userInput="second_store_view" selector="{{AdminNewStoreSection.storeCodeTextField}}" stepKey="fillStoreViewCode"/> + <selectOption userInput="1" selector="{{AdminNewStoreSection.statusDropdown}}" stepKey="enableStoreViewStatus"/> + <click selector="{{AdminStoresMainActionsSection.saveButton}}" stepKey="clickStoreViewSaveButton"/> + <waitForElementVisible selector="{{AdminNewStoreSection.acceptNewStoreViewCreation}}" stepKey="waitForAcceptNewStoreViewCreationModal" /> + <conditionalClick selector="{{AdminNewStoreSection.acceptNewStoreViewCreation}}" dependentSelector="{{AdminNewStoreSection.acceptNewStoreViewCreation}}" visible="true" stepKey="AcceptNewStoreViewCreation"/> + <waitForElementVisible selector="{{AdminStoresGridSection.storeFilterTextField}}" stepKey="waitForPageReolad"/> + <see userInput="You saved the store view." stepKey="seeSaveMessage" /> + + <!--go to admin and open product edit page to disable product all store view --> + <amOnPage url="{{AdminProductEditPage.url($$createConfigProduct.id$$)}}" stepKey="goToProductEditPage"/> + <waitForPageLoad stepKey="waitEditPage"/> + <click selector="{{AdminProductFormSection.enableProductLabel}}" stepKey="disableProductForAllStoreView"/> + <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSaveButton2"/> + <waitForLoadingMaskToDisappear stepKey="waitForProductPageSave1" /> + <dontSeeCheckboxIsChecked selector="{{AdminProductFormSection.enableProduct}}" stepKey="dontSeeCheckboxEnableProductIsChecked"/> + + <!-- Disable each of the child products for All Store views --> + <click selector="{{AdminProductFormConfigurationsSection.actionsBtn('1')}}" stepKey="clickToExpandActionsForFirstVariation1"/> + <click selector="{{AdminProductFormConfigurationsSection.disableProductBtn}}" stepKey="clickDisableChildProduct1"/> + + <click selector="{{AdminProductFormConfigurationsSection.actionsBtn('2')}}" stepKey="clickToExpandActionsForSecondVariation1"/> + <click selector="{{AdminProductFormConfigurationsSection.disableProductBtn}}" stepKey="clickDisableChildProduct2"/> + + <!-- Add product to second website --> + <click selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="openProductInWebsitesSection1"/> + <click selector="{{ProductInWebsitesSection.website('Second Website')}}" stepKey="selectSecondWebsite"/> + <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSave"/> + <waitForLoadingMaskToDisappear stepKey="waitForProductPageSave"/> + <seeElement selector="{{AdminProductMessagesSection.successMessage}}" stepKey="seeSaveProductMessage"/> + + <!-- switch to the second store view --> + <click selector="{{AdminProductFormActionSection.changeStoreButton}}" stepKey="clickStoreviewSwitcher"/> + <click selector="{{AdminProductFormActionSection.selectStoreView('Second Store View')}}" stepKey="chooseStoreView"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="acceptStoreSwitchingMessage"/> + <!--<waitForPageLoad stepKey="waitForStoreViewSwitched"/>--> + <waitForPageLoad time="30" stepKey="waitForPageLoad9"/> + <see userInput="Second Store View" selector="{{AdminMainActionsSection.storeSwitcher}}" stepKey="seeNewStoreViewName"/> + + <!-- enable the config product for the second store --> + <waitForElementVisible selector="{{AdminProductFormSection.enableProductLabel}}" stepKey="waitForProductEnableSlider"/> + <click selector="{{AdminProductFormSection.enableProductLabel}}" stepKey="enableProductForSecondStoreView"/> + <seeCheckboxIsChecked selector="{{AdminProductFormSection.enableProduct}}" stepKey="seeThatProductIsEnabled"/> + <actionGroup ref="AdminFormSaveAndClose" stepKey="enabledConfigProductSecondStore"/> + + <!--go to admin and open product edit page to enable child product for second store view --> + <amOnPage url="{{AdminProductEditPage.url($$createConfigProduct.id$$)}}" stepKey="goToProductEditPage2"/> + <waitForPageLoad stepKey="waitEditPage2"/> + <click selector="{{AdminProductFormActionSection.changeStoreButton}}" stepKey="clickStoreviewSwitcher1"/> + <click selector="{{AdminProductFormActionSection.selectStoreView('Second Store View')}}" stepKey="chooseStoreView1"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="acceptStoreSwitchingMessage1"/> + <waitForPageLoad time="30" stepKey="waitForPageLoad8"/> + <see userInput="Second Store View" selector="{{AdminMainActionsSection.storeSwitcher}}" stepKey="seeNewStoreViewName1"/> + + <click selector="{{AdminProductFormConfigurationsSection.actionsBtn('1')}}" stepKey="clickToExpandActionsForFirstVariation2"/> + <click selector="{{AdminProductFormConfigurationsSection.enableProductBtn}}" stepKey="clickEnableChildProduct1"/> + <click selector="{{AdminProductFormConfigurationsSection.actionsBtn('2')}}" stepKey="clickToExpandActionsForSecondVariation2"/> + <click selector="{{AdminProductFormConfigurationsSection.enableProductBtn}}" stepKey="clickEnableChildProduct2"/> + <actionGroup ref="AdminFormSaveAndClose" stepKey="saveAll"/> + + <!-- assert second store view storefront category list page --> + <amOnPage url="/second_store_view/" stepKey="amOnsecondStoreFront1"/> + <waitForPageLoad stepKey="waitForPageLoad31"/> + <click userInput="$$createCategory.name$$" stepKey="clickOnCategoryName1"/> + <waitForPageLoad stepKey="waitForPageLoad41"/> + <see userInput="$$createConfigProduct.name$$" stepKey="assertProductPresent1"/> + + <!--go to admin and open child product1 and assign it to the second website --> + <amOnPage url="{{AdminProductEditPage.url($$createConfigChildProduct1.id$$)}}" stepKey="goToProduct1EditPage1"/> + <waitForPageLoad stepKey="waitChild1EditPageToLoad"/> + <click selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="openProduct1InWebsitesSection"/> + <click selector="{{ProductInWebsitesSection.website('Second Website')}}" stepKey="selectSecondWebsite1"/> + <actionGroup ref="AdminFormSaveAndClose" stepKey="saveUpdatedChild1Again"/> + + <!--go to admin again and open child product1 and enable for second store view--> + <amOnPage url="{{AdminProductEditPage.url($$createConfigChildProduct1.id$$)}}" stepKey="goToProduct1EditPage"/> + <waitForPageLoad stepKey="waitChild1EditPageToLoad1"/> + <click selector="{{AdminProductFormActionSection.changeStoreButton}}" stepKey="clickStoreviewSwitcherP1"/> + <click selector="{{AdminProductFormActionSection.selectStoreView('Second Store View')}}" stepKey="chooseStoreView2P1"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="acceptStoreSwitchingMessageP1"/> + <waitForPageLoad time="30" stepKey="waitForStoreViewSwitchedP1"/> + <see userInput="Second Store View" selector="{{AdminMainActionsSection.storeSwitcher}}" stepKey="seeNewStoreViewNameP1"/> + <waitForElementVisible selector="{{AdminProductFormSection.enableProductLabel}}" stepKey="waitForProductEnableSliderP1"/> + <click selector="{{AdminProductFormSection.enableProductLabel}}" stepKey="enableProductForSecondStoreViewP1"/> + <seeCheckboxIsChecked selector="{{AdminProductFormSection.enableProduct}}" stepKey="seeThatProduct1IsEnabled"/> + <actionGroup ref="AdminFormSaveAndClose" stepKey="save2UpdatedChild1"/> + + <!--go to admin and open child product2 edit page and assign it to the second website --> + <amOnPage url="{{AdminProductEditPage.url($$createConfigChildProduct2.id$$)}}" stepKey="goToProduct2EditPage"/> + <waitForPageLoad stepKey="waitChild2EditPageToLoad"/> + <click selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="openProduct2InWebsitesSection"/> + <click selector="{{ProductInWebsitesSection.website('Second Website')}}" stepKey="selectSecondWebsite2"/> + <actionGroup ref="AdminFormSaveAndClose" stepKey="saveUpdatedChild2"/> + + <!--go to admin again and open child product2 and enable for second store view--> + <amOnPage url="{{AdminProductEditPage.url($$createConfigChildProduct2.id$$)}}" stepKey="goToProduct2EditPage2"/> + <waitForPageLoad stepKey="waitChild2EditPageToLoad1"/> + <click selector="{{AdminProductFormActionSection.changeStoreButton}}" stepKey="clickStoreviewSwitcherP2"/> + <click selector="{{AdminProductFormActionSection.selectStoreView('Second Store View')}}" stepKey="chooseStoreView2P2"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="acceptStoreSwitchingMessageP2"/> + <waitForPageLoad time="30" stepKey="waitForStoreViewSwitchedP2"/> + <see userInput="Second Store View" selector="{{AdminMainActionsSection.storeSwitcher}}" stepKey="seeNewStoreViewNameP2"/> + <waitForElementVisible selector="{{AdminProductFormSection.enableProductLabel}}" stepKey="waitForProductEnableSliderP2"/> + <click selector="{{AdminProductFormSection.enableProductLabel}}" stepKey="enableProductForSecondStoreViewP2"/> + <seeCheckboxIsChecked selector="{{AdminProductFormSection.enableProduct}}" stepKey="seeThatProduct2IsEnabled"/> + <actionGroup ref="AdminFormSaveAndClose" stepKey="save2UpdatedChild2"/> + + <!-- assert storefront category list page --> + <amOnPage url="/second_store_view/" stepKey="amOnsecondStoreFront"/> + <waitForPageLoad stepKey="waitForPageLoad3"/> + <click userInput="$$createCategory.name$$" stepKey="clickOnCategoryName"/> + <waitForPageLoad stepKey="waitForPageLoad4"/> + <see userInput="$$createConfigProduct.name$$" stepKey="assertProductPresent"/> + <dontSee userInput="$$createConfigChildProduct1.price$$" stepKey="assertProductPricePresent"/> + </test> +</tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminCreateNewStoreGroupActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminCreateNewStoreGroupActionGroup.xml new file mode 100644 index 0000000000000..83aa1a4735935 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminCreateNewStoreGroupActionGroup.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Admin creates new Store group --> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateNewStoreGroupActionGroup"> + <amOnPage url="{{AdminSystemStoreGroupPage.url}}" stepKey="navigateToNewStoreView"/> + <waitForPageLoad stepKey="waitForPageLoad1" /> + <!--Create Store group --> + <selectOption selector="{{AdminNewStoreGroupSection.storeGrpWebsiteDropdown}}" userInput="Second Website" stepKey="selectWebsite" /> + <fillField selector="{{AdminNewStoreGroupSection.storeGrpNameTextField}}" userInput="Second Store" stepKey="enterStoreGroupName" /> + <fillField selector="{{AdminNewStoreGroupSection.storeGrpCodeTextField}}" userInput="second_store" stepKey="enterStoreGroupCode" /> + <selectOption selector="{{AdminNewStoreGroupSection.storeRootCategoryDropdown}}" userInput="Default Category" stepKey="chooseRootCategory" /> + <click selector="{{AdminStoreGroupActionsSection.saveButton}}" stepKey="clickSaveStoreGroup" /> + <waitForElementVisible selector="{{AdminStoresGridSection.storeGrpFilterTextField}}" stepKey="waitForStoreGridReload"/> + <see userInput="You saved the store." stepKey="seeSavedMessage" /> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminCreateWebsiteActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminCreateWebsiteActionGroup.xml new file mode 100644 index 0000000000000..c34e6c0814bb8 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminCreateWebsiteActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Admin creates new custom website --> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateWebsiteActionGroup"> + <amOnPage url="{{AdminSystemStoreWebsitePage.url}}" stepKey="navigateToNewWebsitePage"/> + <waitForPageLoad stepKey="waitForStoresPageLoad"/> + <!--Create Website--> + <fillField selector="{{AdminNewWebsiteSection.name}}" userInput="Second Website" stepKey="enterWebsiteName" /> + <fillField selector="{{AdminNewWebsiteSection.code}}" userInput="second_website" stepKey="enterWebsiteCode" /> + <click selector="{{AdminNewWebsiteActionsSection.saveWebsite}}" stepKey="clickSaveWebsite" /> + <waitForElementVisible selector="{{AdminStoresGridSection.websiteFilterTextField}}" stepKey="waitForStoreGridToReload"/> + <see userInput="You saved the website." stepKey="seeSavedMessage" /> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminDeleteWebsiteActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminDeleteWebsiteActionGroup.xml new file mode 100644 index 0000000000000..9b61315f0d5b8 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/ActionGroup/AdminDeleteWebsiteActionGroup.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminDeleteWebsiteActionGroup"> + <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="amOnAdminSystemStorePage"/> + <click selector="{{AdminStoresGridSection.resetButton}}" stepKey="resetSearchFilter"/> + <fillField userInput="Second Website" selector="{{AdminStoresGridSection.websiteFilterTextField}}" stepKey="fillSearchWebsiteField"/> + <click selector="{{AdminStoresGridSection.searchButton}}" stepKey="clickSearchButton"/> + <see userInput="Second Website" selector="{{AdminStoresGridSection.websiteNameInFirstRow}}" stepKey="verifyThatCorrectWebsiteFound"/> + <click selector="{{AdminStoresGridSection.websiteNameInFirstRow}}" stepKey="clickEditExistingStoreRow"/> + <waitForPageLoad stepKey="waitForStoreToLoad"/> + <click selector="{{AdminStoresMainActionsSection.deleteButton}}" stepKey="clickDeleteWebsiteButtonOnEditWebsitePage"/> + <selectOption userInput="No" selector="{{AdminStoresDeleteStoreGroupSection.createDbBackup}}" stepKey="setCreateDbBackupToNo"/> + <click selector="{{AdminStoresDeleteStoreGroupSection.deleteStoreGroupButton}}" stepKey="clickDeleteWebsiteButton"/> + <waitForElementVisible selector="{{AdminStoresGridSection.websiteFilterTextField}}" stepKey="waitForStoreGridToReload"/> + <see userInput="You deleted the website." stepKey="seeSavedMessage"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Page/AdminSystemStoreGroupPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Page/AdminSystemStoreGroupPage.xml new file mode 100644 index 0000000000000..9c203241283dc --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Page/AdminSystemStoreGroupPage.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd"> + <page name="AdminSystemStoreGroupPage" url="admin/system_store/newGroup" module="Magento_Store" area="admin"> + <section name="AdminNewStoreGroupSection"/> + </page> +</pages> \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Page/AdminSystemStoreWebsitePage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Page/AdminSystemStoreWebsitePage.xml new file mode 100644 index 0000000000000..6b28b2f04ea09 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Page/AdminSystemStoreWebsitePage.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd"> + <page name="AdminSystemStoreWebsitePage" url="admin/system_store/newWebsite" module="Magento_Store" area="admin"> + <section name="AdminNewWebsiteSection"/> + </page> +</pages> \ No newline at end of file diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewStoreGroupSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewStoreGroupSection.xml index 7357ee0771239..be22aa7f8c120 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewStoreGroupSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewStoreGroupSection.xml @@ -10,6 +10,6 @@ <element name="storeGrpWebsiteDropdown" type="select" selector="#group_website_id"/> <element name="storeGrpNameTextField" type="input" selector="#group_name"/> <element name="storeGrpCodeTextField" type="input" selector="#group_code"/> - <element name="storeRootCategoryDropdown" type="button" selector="#group_root_category_id"/> + <element name="storeRootCategoryDropdown" type="select" selector="#group_root_category_id"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewWebsiteActionsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewWebsiteActionsSection.xml new file mode 100644 index 0000000000000..18d1ef2642ef8 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Store/Section/AdminNewWebsiteActionsSection.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> + <section name="AdminNewWebsiteActionsSection"> + <element name="saveWebsite" type="button" selector="#save" timeout="30"/> + </section> +</sections> \ No newline at end of file From d2e76685cd2e41567fd3238f45c1819ef717a2d9 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Fri, 1 Jun 2018 20:32:14 -0500 Subject: [PATCH 0917/2023] MAGETWO-92247: Verify that product price is displayed on additional storefront if product is disabled for default store view - skip test --- .../Test/ConfigurableProductPriceAdditionalStoreViewTest.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml index 56a9020c3a14d..0fb1e22e48e05 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/ConfigurableProduct/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml @@ -15,8 +15,7 @@ <description value="Configurable product price should not disappear for additional stores on frontEnd if disabled for default store"/> <severity value="CRITICAL"/> <testCaseId value="MAGETWO-92247"/> - <group value="configurable"/> - <group value="product"/> + <group value="skip"/> </annotations> <before> From 3c0946d36ee827530f410eacbd7d5fb93a725ff8 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@magento.com> Date: Fri, 1 Jun 2018 17:12:50 -0500 Subject: [PATCH 0918/2023] MAGETWO-91436: Custom Options are corruputed when saving product to a different website - added functional test to cover the usecase --- ...ductWithCustomOptionsSecondWebsiteTest.xml | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml new file mode 100644 index 0000000000000..cc33059dd10b6 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="SaveProductWithCustomOptionsAdditionalWebsiteTest"> + <annotations> + <features value="Save a product with Custom Options and assign to a different website"/> + <stories value="Purchase a product with Custom Options of different types"/> + <title value="You should be able to save a product with custom options assigned to a different website"/> + <description value="Custom Options should not be split when saving the product after assigning to a different website"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-91436"/> + <group value="product"/> + </annotations> + + <after> + <actionGroup ref="ResetWebUrlOptions" stepKey="resetUrlOption"/> + <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"/> + + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + </after> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="EnableWebUrlOptions" stepKey="addStoreCodeToUrls"/> + <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="addnewWebsite"/> + <actionGroup ref="AdminCreateNewStoreGroupActionGroup" stepKey="addNewStoreGroup"/> + + <!--Create Store view --> + <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="amOnAdminSystemStorePage"/> + <click selector="{{AdminStoresMainActionsSection.createStoreViewButton}}" stepKey="createStoreViewButton"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <selectOption userInput="Second Store" selector="{{AdminNewStoreSection.storeGrpDropdown}}" stepKey="selectStoreGroup"/> + <fillField userInput="Second Store View" selector="{{AdminNewStoreSection.storeNameTextField}}" stepKey="fillStoreViewName"/> + <fillField userInput="second_store_view" selector="{{AdminNewStoreSection.storeCodeTextField}}" stepKey="fillStoreViewCode"/> + <selectOption userInput="1" selector="{{AdminNewStoreSection.statusDropdown}}" stepKey="enableStoreViewStatus"/> + <click selector="{{AdminStoresMainActionsSection.saveButton}}" stepKey="clickStoreViewSaveButton"/> + <waitForElementVisible selector="{{AdminNewStoreSection.acceptNewStoreViewCreation}}" stepKey="waitForAcceptNewStoreViewCreationModal" /> + <conditionalClick selector="{{AdminNewStoreSection.acceptNewStoreViewCreation}}" dependentSelector="{{AdminNewStoreSection.acceptNewStoreViewCreation}}" visible="true" stepKey="AcceptNewStoreViewCreation"/> + <waitForElementVisible selector="{{AdminStoresGridSection.storeFilterTextField}}" stepKey="waitForPageReolad"/> + <see userInput="You saved the store view." stepKey="seeSaveMessage" /> + + <!--Create a Simple Product with Custom Options --> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToCatalogProductGrid"/> + <click selector="{{AdminProductGridActionSection.addProductToggle}}" stepKey="clickAddProductDropdown"/> + <click selector="{{AdminProductGridActionSection.addSimpleProduct}}" stepKey="clickAddSimpleProduct"/> + <fillField userInput="{{_defaultProduct.name}}" selector="{{AdminProductFormSection.productName}}" stepKey="fillName"/> + <fillField userInput="{{_defaultProduct.sku}}" selector="{{AdminProductFormSection.productSku}}" stepKey="fillSKU"/> + <fillField userInput="{{_defaultProduct.price}}" selector="{{AdminProductFormSection.productPrice}}" stepKey="fillPrice"/> + <fillField userInput="{{_defaultProduct.quantity}}" selector="{{AdminProductFormSection.productQuantity}}" stepKey="fillQuantity"/> + + <!--<click selector="{{AdminProductCustomizableOptionsSection.customezableOptions}}" stepKey="openCustomOptionsSection"/>--> + <conditionalClick selector="{{AdminProductCustomizableOptionsSection.customezableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.checkIfCustomizableOptionsTabOpen}}" visible="true" stepKey="clickIfContentTabCloses2"/> + <click selector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" stepKey="clickAddOption"/> + <waitForPageLoad stepKey="waitAfterAddOption"/> + <fillField selector="input[name='product[options][0][title]']" userInput="Radio Option" stepKey="fillOptionTitle"/> + <click selector=".admin__dynamic-rows[data-index='options'] .action-select" stepKey="openOptionTypeDropDown"/> + <click selector=".admin__dynamic-rows[data-index='options'] .action-menu._active li:nth-of-type(3) li:nth-of-type(2)" stepKey="selectRadioButtonType"/> + + <!--Add Option Values --> + <click selector="{{AdminProductCustomizableOptionsSection.clickAddValue('Radio Option')}}" stepKey="clickAddValue1"/> + <fillField selector="{{AdminProductCustomizableOptionsSection.fillOptionValueTitle('Radio Option', '0')}}" userInput="option 1" stepKey="fillOptionValueTitle1"/> + <fillField selector="{{AdminProductCustomizableOptionsSection.fillOptionValuePrice('Radio Option', '0')}}" userInput="5" stepKey="fillOptionValuePrice1"/> + + <click selector="{{AdminProductCustomizableOptionsSection.clickAddValue('Radio Option')}}" stepKey="clickAddValue2"/> + <fillField selector="{{AdminProductCustomizableOptionsSection.fillOptionValueTitle('Radio Option', '1')}}" userInput="option 2" stepKey="fillOptionValueTitle2"/> + <fillField selector="{{AdminProductCustomizableOptionsSection.fillOptionValuePrice('Radio Option', '1')}}" userInput="6" stepKey="fillOptionValuePrice2"/> + + <click selector="{{AdminProductCustomizableOptionsSection.clickAddValue('Radio Option')}}" stepKey="clickAddValue3"/> + <fillField selector="{{AdminProductCustomizableOptionsSection.fillOptionValueTitle('Radio Option', '2')}}" userInput="option 3" stepKey="fillOptionValueTitle3"/> + <fillField selector="{{AdminProductCustomizableOptionsSection.fillOptionValuePrice('Radio Option', '2')}}" userInput="7" stepKey="fillOptionValuePrice3"/> + + <!--Save the product with custom options --> + <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSaveButton"/> + <waitForLoadingMaskToDisappear stepKey="waitProductPageSave"/> + <seeElement selector="{{AdminProductMessagesSection.successMessage}}" stepKey="seeProductSavedMessage"/> + + <!-- Add this product to second website --> + <click selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="openProductInWebsitesSection1"/> + <click selector="{{ProductInWebsitesSection.website('Second Website')}}" stepKey="selectSecondWebsite"/> + <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickSave"/> + <waitForLoadingMaskToDisappear stepKey="waitForProductPagetoSaveAgain"/> + <seeElement selector="{{AdminProductMessagesSection.successMessage}}" stepKey="seeSaveProductMessageAgain"/> + + <click selector="{{AdminProductCustomizableOptionsSection.customezableOptions}}" stepKey="openCustomOptionsSection2"/> + <seeNumberOfElements selector=".admin__dynamic-rows[data-index='values'] tr.data-row" userInput="3" stepKey="see4RowsOfOptions"/> + + </test> +</tests> \ No newline at end of file From eca36b2809a25e42d2f070caca533b163e48bad0 Mon Sep 17 00:00:00 2001 From: Ankur Raiyani <ankur@seepossible.com> Date: Sat, 2 Jun 2018 09:40:00 +0530 Subject: [PATCH 0919/2023] Merge branch '2.3-develop' of https://github.com/magento/magento2 into 2.3-develop # Conflicts: # app/code/Magento/Sales/etc/di.xml --- app/code/Magento/Sales/etc/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index ab758f4d4c15f..ce2948983edbe 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -686,7 +686,7 @@ <item name="shipping_address" xsi:type="object">ShippingAddressAggregator</item> <item name="shipping_information" xsi:type="string">sales_order.shipping_description</item> <item name="subtotal" xsi:type="string">sales_invoice.base_subtotal</item> - <item name="shipping_and_handling" xsi:type="string">sales_order.base_shipping_amount</item> + <item name="shipping_and_handling" xsi:type="string">sales_invoice.base_shipping_amount</item> <item name="base_grand_total" xsi:type="string">sales_invoice.base_grand_total</item> <item name="grand_total" xsi:type="string">sales_invoice.grand_total</item> <item name="created_at" xsi:type="string">sales_invoice.created_at</item> From ac220b7845735567a75108593cf19456a5b21cb7 Mon Sep 17 00:00:00 2001 From: Ankur Raiyani <ankur@seepossible.com> Date: Sat, 2 Jun 2018 09:49:58 +0530 Subject: [PATCH 0920/2023] Updated 2.3-develop patch branch --- app/code/Magento/Sales/etc/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index ce2948983edbe..ab758f4d4c15f 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -686,7 +686,7 @@ <item name="shipping_address" xsi:type="object">ShippingAddressAggregator</item> <item name="shipping_information" xsi:type="string">sales_order.shipping_description</item> <item name="subtotal" xsi:type="string">sales_invoice.base_subtotal</item> - <item name="shipping_and_handling" xsi:type="string">sales_invoice.base_shipping_amount</item> + <item name="shipping_and_handling" xsi:type="string">sales_order.base_shipping_amount</item> <item name="base_grand_total" xsi:type="string">sales_invoice.base_grand_total</item> <item name="grand_total" xsi:type="string">sales_invoice.grand_total</item> <item name="created_at" xsi:type="string">sales_invoice.created_at</item> From 12041e1ec05bd78cbfa220d4f98dbf50e1889d6f Mon Sep 17 00:00:00 2001 From: Ankur Raiyani <ankur@seepossible.com> Date: Sat, 2 Jun 2018 09:51:13 +0530 Subject: [PATCH 0921/2023] Updated 2.3-develop patch branch --- app/code/Magento/Sales/etc/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index ab758f4d4c15f..ce2948983edbe 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -686,7 +686,7 @@ <item name="shipping_address" xsi:type="object">ShippingAddressAggregator</item> <item name="shipping_information" xsi:type="string">sales_order.shipping_description</item> <item name="subtotal" xsi:type="string">sales_invoice.base_subtotal</item> - <item name="shipping_and_handling" xsi:type="string">sales_order.base_shipping_amount</item> + <item name="shipping_and_handling" xsi:type="string">sales_invoice.base_shipping_amount</item> <item name="base_grand_total" xsi:type="string">sales_invoice.base_grand_total</item> <item name="grand_total" xsi:type="string">sales_invoice.grand_total</item> <item name="created_at" xsi:type="string">sales_invoice.created_at</item> From 7259c4bc329c3b9b9541d3113bb46f3ba2f131d3 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta <riccardo.tempesta@magespecialist.it> Date: Sat, 2 Jun 2018 12:14:12 +0200 Subject: [PATCH 0922/2023] Fulltext replacement with like condition when a SearchCriteria is applied to a DB collection. See https://github.com/magento-engcom/msi/issues/1221 --- .../CollectionProcessor/FilterProcessor.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/internal/Magento/Framework/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php b/lib/internal/Magento/Framework/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php index b663a3a2f733c..c9f10c183b50c 100644 --- a/lib/internal/Magento/Framework/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php +++ b/lib/internal/Magento/Framework/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php @@ -72,6 +72,15 @@ private function addFilterGroupToCollection( if (!$isApplied) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $fields[] = $this->getFieldMapping($filter->getField()); + + if ($condition === 'fulltext') { + // NOTE: This is not a fulltext search, but the best way to search something when + // a SearchCriteria with "fulltext" condition is provided over a MySQL table + // (see https://github.com/magento-engcom/msi/issues/1221) + $condition = 'like'; + $filter->setValue('%' . $filter->getValue() . '%'); + } + $conditions[] = [$condition => $filter->getValue()]; } } From 38180f2cef75272cb193870e0c2317d0213ff8e3 Mon Sep 17 00:00:00 2001 From: Sergii Gozhedrianov <s.gozhedrianov@youwe.nl> Date: Sat, 2 Jun 2018 15:52:27 +0200 Subject: [PATCH 0923/2023] removed category_ids and tax_class_id from filterable fields list --- app/code/Magento/CatalogGraphQl/etc/schema.graphqls | 1 - app/code/Magento/TaxGraphQl/etc/schema.graphqls | 4 ---- 2 files changed, 5 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 5d9e174f169d1..04002e08795a0 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -441,7 +441,6 @@ input ProductFilterInput @doc(description: "ProductFilterInput defines the filte min_price: FilterTypeInput @doc(description:"The numeric minimal price of the product. Do not include the currency code.") max_price: FilterTypeInput @doc(description:"The numeric maximal price of the product. Do not include the currency code.") special_price: FilterTypeInput @doc(description:"The numeric special price of the product. Do not include the currency code.") - category_ids: FilterTypeInput @doc(description: "An array of category IDs the product belongs to") options_container: FilterTypeInput @doc(description: "If the product has multiple options, determines where they appear on the product page") required_options: FilterTypeInput @doc(description: "Indicates whether the product has required options") has_options: FilterTypeInput @doc(description: "Indicates whether additional attributes have been created for the product") diff --git a/app/code/Magento/TaxGraphQl/etc/schema.graphqls b/app/code/Magento/TaxGraphQl/etc/schema.graphqls index b39673f5431f1..eafb390983973 100644 --- a/app/code/Magento/TaxGraphQl/etc/schema.graphqls +++ b/app/code/Magento/TaxGraphQl/etc/schema.graphqls @@ -1,10 +1,6 @@ # Copyright © Magento, Inc. All rights reserved. # See COPYING.txt for license details. -input ProductFilterInput { - tax_class_id: FilterTypeInput -} - interface ProductInterface { tax_class_id: Int } From ff02c919a932658795afbb3654c6b0e738dedd47 Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun <mitry@atwix.com> Date: Sat, 2 Jun 2018 22:52:37 +0300 Subject: [PATCH 0924/2023] Add missing property, fixed incorrect proprty type, add missing throws to PHPDocs --- app/code/Magento/Ui/Model/Export/ConvertToCsv.php | 10 +++++++++- app/code/Magento/Ui/Model/Export/ConvertToXml.php | 12 +++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/Model/Export/ConvertToCsv.php b/app/code/Magento/Ui/Model/Export/ConvertToCsv.php index e8136c7520054..40b10749db21e 100644 --- a/app/code/Magento/Ui/Model/Export/ConvertToCsv.php +++ b/app/code/Magento/Ui/Model/Export/ConvertToCsv.php @@ -6,8 +6,10 @@ namespace Magento\Ui\Model\Export; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\Ui\Component\MassAction\Filter; /** @@ -16,7 +18,7 @@ class ConvertToCsv { /** - * @var DirectoryList + * @var WriteInterface */ protected $directory; @@ -30,11 +32,17 @@ class ConvertToCsv */ protected $pageSize = null; + /** + * @var Filter + */ + protected $filter; + /** * @param Filesystem $filesystem * @param Filter $filter * @param MetadataProvider $metadataProvider * @param int $pageSize + * @throws FileSystemException */ public function __construct( Filesystem $filesystem, diff --git a/app/code/Magento/Ui/Model/Export/ConvertToXml.php b/app/code/Magento/Ui/Model/Export/ConvertToXml.php index fca5f10126765..5f6e45a948f24 100644 --- a/app/code/Magento/Ui/Model/Export/ConvertToXml.php +++ b/app/code/Magento/Ui/Model/Export/ConvertToXml.php @@ -10,8 +10,10 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Convert\Excel; use Magento\Framework\Convert\ExcelFactory; +use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\Ui\Component\MassAction\Filter; /** @@ -20,7 +22,7 @@ class ConvertToXml { /** - * @var DirectoryList + * @var WriteInterface */ protected $directory; @@ -49,12 +51,18 @@ class ConvertToXml */ protected $fields; + /** + * @var Filter + */ + protected $filter; + /** * @param Filesystem $filesystem * @param Filter $filter * @param MetadataProvider $metadataProvider * @param ExcelFactory $excelFactory * @param SearchResultIteratorFactory $iteratorFactory + * @throws FileSystemException */ public function __construct( Filesystem $filesystem, @@ -87,6 +95,7 @@ protected function getOptions() * Returns DB fields list * * @return array + * @throws LocalizedException */ protected function getFields() { @@ -102,6 +111,7 @@ protected function getFields() * * @param DocumentInterface $document * @return array + * @throws LocalizedException */ public function getRowData(DocumentInterface $document) { From f0eb5406d3450c54aedcac24d3c01144da5862bc Mon Sep 17 00:00:00 2001 From: Danny Verkade <danny@cream.nl> Date: Sat, 2 Jun 2018 23:19:09 +0200 Subject: [PATCH 0925/2023] Fixed typos: - Changed disply to display - Changed addtional to additional - Changed beging to begin --- .../Adminhtml/Order/Create/Sidebar/AbstractSidebar.php | 2 +- .../Ui/view/base/web/js/form/components/fieldset.js | 8 ++++---- .../Magento/Ui/view/base/web/js/form/components/group.js | 8 ++++---- setup/pub/angular-sanitize/angular-sanitize.js | 4 ++-- setup/pub/angular-sanitize/angular-sanitize.min.js.map | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/AbstractSidebar.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/AbstractSidebar.php index e0b442036af90..06c6a9eb0652b 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/AbstractSidebar.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/AbstractSidebar.php @@ -71,7 +71,7 @@ public function canDisplay() } /** - * Retrieve disply item qty availability + * Retrieve display item qty availability * * @return false */ diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/fieldset.js b/app/code/Magento/Ui/view/base/web/js/form/components/fieldset.js index 371a0773f9d7e..b729dd3127d90 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/fieldset.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/fieldset.js @@ -115,14 +115,14 @@ define([ * @returns {Group} Chainable. */ _setClasses: function () { - var addtional = this.additionalClasses, + var additional = this.additionalClasses, classes; - if (_.isString(addtional)) { - addtional = this.additionalClasses.split(' '); + if (_.isString(additional)) { + additional = this.additionalClasses.split(' '); classes = this.additionalClasses = {}; - addtional.forEach(function (name) { + additional.forEach(function (name) { classes[name] = true; }, this); } diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/group.js b/app/code/Magento/Ui/view/base/web/js/form/components/group.js index f6937cffe1f2f..8c5950f7e2fa1 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/group.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/group.js @@ -58,14 +58,14 @@ define([ * @returns {Group} Chainable. */ _setClasses: function () { - var addtional = this.additionalClasses, + var additional = this.additionalClasses, classes; - if (_.isString(addtional)) { - addtional = this.additionalClasses.split(' '); + if (_.isString(additional)) { + additional = this.additionalClasses.split(' '); classes = this.additionalClasses = {}; - addtional.forEach(function (name) { + additional.forEach(function (name) { classes[name] = true; }, this); } diff --git a/setup/pub/angular-sanitize/angular-sanitize.js b/setup/pub/angular-sanitize/angular-sanitize.js index b7ec2820dd7fe..6004460cd17eb 100644 --- a/setup/pub/angular-sanitize/angular-sanitize.js +++ b/setup/pub/angular-sanitize/angular-sanitize.js @@ -159,7 +159,7 @@ END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, BEGIN_TAG_REGEXP = /^</, - BEGING_END_TAGE_REGEXP = /^<\s*\//, + BEGIN_END_TAGE_REGEXP = /^<\s*\//, COMMENT_REGEXP = /<!--(.*?)-->/g, DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i, CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g, @@ -260,7 +260,7 @@ chars = false; } // end tag - } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { + } else if ( BEGIN_END_TAGE_REGEXP.test(html) ) { match = html.match( END_TAG_REGEXP ); if ( match ) { diff --git a/setup/pub/angular-sanitize/angular-sanitize.min.js.map b/setup/pub/angular-sanitize/angular-sanitize.min.js.map index 0c993a6ed2afb..0310ddce9c937 100644 --- a/setup/pub/angular-sanitize/angular-sanitize.min.js.map +++ b/setup/pub/angular-sanitize/angular-sanitize.min.js.map @@ -4,5 +4,5 @@ "lineCount":13, "mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAiJtCC,QAASA,EAAY,CAACC,CAAD,CAAQ,CAC3B,IAAIC,EAAM,EACGC,EAAAC,CAAmBF,CAAnBE,CAAwBN,CAAAO,KAAxBD,CACbH,MAAA,CAAaA,CAAb,CACA,OAAOC,EAAAI,KAAA,CAAS,EAAT,CAJoB,CAmE7BC,QAASA,EAAO,CAACC,CAAD,CAAM,CAAA,IAChBC,EAAM,EAAIC,EAAAA,CAAQF,CAAAG,MAAA,CAAU,GAAV,CAAtB,KAAsCC,CACtC,KAAKA,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgBF,CAAAG,OAAhB,CAA8BD,CAAA,EAA9B,CAAmCH,CAAA,CAAIC,CAAA,CAAME,CAAN,CAAJ,CAAA,CAAgB,CAAA,CACnD,OAAOH,EAHa,CAmBtBK,QAASA,EAAU,CAAEC,CAAF,CAAQC,CAAR,CAAkB,CAiFnCC,QAASA,EAAa,CAAEC,CAAF,CAAOC,CAAP,CAAgBC,CAAhB,CAAsBC,CAAtB,CAA8B,CAClDF,CAAA,CAAUrB,CAAAwB,UAAA,CAAkBH,CAAlB,CACV,IAAKI,CAAA,CAAeJ,CAAf,CAAL,CACE,IAAA,CAAQK,CAAAC,KAAA,EAAR,EAAwBC,CAAA,CAAgBF,CAAAC,KAAA,EAAhB,CAAxB,CAAA,CACEE,CAAA,CAAa,EAAb,CAAiBH,CAAAC,KAAA,EAAjB,CAICG,EAAA,CAAwBT,CAAxB,CAAL,EAA0CK,CAAAC,KAAA,EAA1C,EAA0DN,CAA1D,EACEQ,CAAA,CAAa,EAAb,CAAiBR,CAAjB,CAKF,EAFAE,CAEA,CAFQQ,CAAA,CAAcV,CAAd,CAER,EAFmC,CAAC,CAACE,CAErC,GACEG,CAAAM,KAAA,CAAYX,CAAZ,CAEF,KAAIY,EAAQ,EAEZX,EAAAY,QAAA,CAAaC,CAAb,CACE,QAAQ,CAACC,CAAD,CAAQC,CAAR,CAAcC,CAAd,CAAiCC,CAAjC,CAAoDC,CAApD,CAAmE,CAMzEP,CAAA,CAAMI,CAAN,CAAA,CAAcI,CAAA,CALFH,CAKE,EAJTC,CAIS,EAHTC,CAGS,EAFT,EAES,CAN2D,CAD7E,CASItB,EAAAwB,MAAJ,EAAmBxB,CAAAwB,MAAA,CAAerB,CAAf,CAAwBY,CAAxB,CAA+BV,CAA/B,CA5B+B,CA+BpDM,QAASA,EAAW,CAAET,CAAF,CAAOC,CAAP,CAAiB,CAAA,IAC/BsB,EAAM,CADyB,CACtB7B,CAEb,IADAO,CACA,CADUrB,CAAAwB,UAAA,CAAkBH,CAAlB,CACV,CAEE,IAAMsB,CAAN,CAAYjB,CAAAX,OAAZ,CAA2B,CAA3B,CAAqC,CAArC,EAA8B4B,CAA9B,EACOjB,CAAA,CAAOiB,CAAP,CADP,EACuBtB,CADvB,CAAwCsB,CAAA,EAAxC;AAIF,GAAY,CAAZ,EAAKA,CAAL,CAAgB,CAEd,IAAM7B,CAAN,CAAUY,CAAAX,OAAV,CAAyB,CAAzB,CAA4BD,CAA5B,EAAiC6B,CAAjC,CAAsC7B,CAAA,EAAtC,CACMI,CAAA0B,IAAJ,EAAiB1B,CAAA0B,IAAA,CAAalB,CAAA,CAAOZ,CAAP,CAAb,CAGnBY,EAAAX,OAAA,CAAe4B,CAND,CATmB,CAhHF,IAC/BE,CAD+B,CACxB1C,CADwB,CACVuB,EAAQ,EADE,CACEC,EAAOV,CAG5C,KAFAS,CAAAC,KAEA,CAFamB,QAAQ,EAAG,CAAE,MAAOpB,EAAA,CAAOA,CAAAX,OAAP,CAAsB,CAAtB,CAAT,CAExB,CAAQE,CAAR,CAAA,CAAe,CACbd,CAAA,CAAQ,CAAA,CAGR,IAAMuB,CAAAC,KAAA,EAAN,EAAuBoB,CAAA,CAAiBrB,CAAAC,KAAA,EAAjB,CAAvB,CAmDEV,CASA,CATOA,CAAAiB,QAAA,CAAiBc,MAAJ,CAAW,kBAAX,CAAgCtB,CAAAC,KAAA,EAAhC,CAA+C,QAA/C,CAAyD,GAAzD,CAAb,CACL,QAAQ,CAACsB,CAAD,CAAMC,CAAN,CAAW,CACjBA,CAAA,CAAOA,CAAAhB,QAAA,CAAaiB,CAAb,CAA6B,IAA7B,CAAAjB,QAAA,CAA2CkB,CAA3C,CAAyD,IAAzD,CAEHlC,EAAAf,MAAJ,EAAmBe,CAAAf,MAAA,CAAesC,CAAA,CAAeS,CAAf,CAAf,CAEnB,OAAO,EALU,CADd,CASP,CAAArB,CAAA,CAAa,EAAb,CAAiBH,CAAAC,KAAA,EAAjB,CA5DF,KAAyD,CAGvD,GAA8B,CAA9B,GAAKV,CAAAoC,QAAA,CAAa,SAAb,CAAL,CAEER,CAEA,CAFQ5B,CAAAoC,QAAA,CAAa,IAAb,CAAmB,CAAnB,CAER,CAAc,CAAd,EAAKR,CAAL,EAAmB5B,CAAAqC,YAAA,CAAiB,QAAjB,CAAwBT,CAAxB,CAAnB,GAAsDA,CAAtD,GACM3B,CAAAqC,QAEJ,EAFqBrC,CAAAqC,QAAA,CAAiBtC,CAAAuC,UAAA,CAAgB,CAAhB,CAAmBX,CAAnB,CAAjB,CAErB,CADA5B,CACA,CADOA,CAAAuC,UAAA,CAAgBX,CAAhB,CAAwB,CAAxB,CACP,CAAA1C,CAAA,CAAQ,CAAA,CAHV,CAJF,KAUO,IAAKsD,CAAAC,KAAA,CAAoBzC,CAApB,CAAL,CAGL,IAFAmB,CAEA,CAFQnB,CAAAmB,MAAA,CAAYqB,CAAZ,CAER,CACExC,CACA;AADOA,CAAAiB,QAAA,CAAcE,CAAA,CAAM,CAAN,CAAd,CAAyB,EAAzB,CACP,CAAAjC,CAAA,CAAQ,CAAA,CAFV,CAHK,IAQA,IAAKwD,CAAAD,KAAA,CAA4BzC,CAA5B,CAAL,CAGL,IAFAmB,CAEA,CAFQnB,CAAAmB,MAAA,CAAYwB,CAAZ,CAER,CACE3C,CAEA,CAFOA,CAAAuC,UAAA,CAAgBpB,CAAA,CAAM,CAAN,CAAArB,OAAhB,CAEP,CADAqB,CAAA,CAAM,CAAN,CAAAF,QAAA,CAAkB0B,CAAlB,CAAkC/B,CAAlC,CACA,CAAA1B,CAAA,CAAQ,CAAA,CAHV,CAHK,IAUK0D,EAAAH,KAAA,CAAsBzC,CAAtB,CAAL,GACLmB,CADK,CACGnB,CAAAmB,MAAA,CAAY0B,CAAZ,CADH,IAIH7C,CAEA,CAFOA,CAAAuC,UAAA,CAAgBpB,CAAA,CAAM,CAAN,CAAArB,OAAhB,CAEP,CADAqB,CAAA,CAAM,CAAN,CAAAF,QAAA,CAAkB4B,CAAlB,CAAoC3C,CAApC,CACA,CAAAhB,CAAA,CAAQ,CAAA,CANL,CAUFA,EAAL,GACE0C,CAKA,CALQ5B,CAAAoC,QAAA,CAAa,GAAb,CAKR,CAHIH,CAGJ,CAHmB,CAAR,CAAAL,CAAA,CAAY5B,CAAZ,CAAmBA,CAAAuC,UAAA,CAAgB,CAAhB,CAAmBX,CAAnB,CAG9B,CAFA5B,CAEA,CAFe,CAAR,CAAA4B,CAAA,CAAY,EAAZ,CAAiB5B,CAAAuC,UAAA,CAAgBX,CAAhB,CAExB,CAAI3B,CAAAf,MAAJ,EAAmBe,CAAAf,MAAA,CAAesC,CAAA,CAAeS,CAAf,CAAf,CANrB,CAzCuD,CA+DzD,GAAKjC,CAAL,EAAaU,CAAb,CACE,KAAMoC,EAAA,CAAgB,UAAhB,CAC4C9C,CAD5C,CAAN,CAGFU,CAAA,CAAOV,CAvEM,CA2EfY,CAAA,EA/EmC,CA2IrCY,QAASA,EAAc,CAACuB,CAAD,CAAQ,CAC7B,GAAI,CAACA,CAAL,CAAc,MAAO,EAIrB,KAAIC,EAAQC,CAAAC,KAAA,CAAaH,CAAb,CACRI,EAAAA,CAAcH,CAAA,CAAM,CAAN,CAClB,KAAII,EAAaJ,CAAA,CAAM,CAAN,CAEjB,IADIK,CACJ,CADcL,CAAA,CAAM,CAAN,CACd,CACEM,CAAAC,UAKA,CALoBF,CAAApC,QAAA,CAAgB,IAAhB,CAAqB,MAArB,CAKpB,CAAAoC,CAAA,CAAU,aAAA,EAAiBC,EAAjB,CACRA,CAAAE,YADQ,CACgBF,CAAAG,UAE5B,OAAON,EAAP,CAAqBE,CAArB,CAA+BD,CAlBF,CA4B/BM,QAASA,EAAc,CAACX,CAAD,CAAQ,CAC7B,MAAOA,EAAA9B,QAAA,CACG,IADH;AACS,OADT,CAAAA,QAAA,CAEG0C,CAFH,CAE4B,QAAQ,CAACZ,CAAD,CAAO,CAC9C,MAAO,IAAP,CAAcA,CAAAa,WAAA,CAAiB,CAAjB,CAAd,CAAoC,GADU,CAF3C,CAAA3C,QAAA,CAKG,IALH,CAKS,MALT,CAAAA,QAAA,CAMG,IANH,CAMS,MANT,CADsB,CAoB/B7B,QAASA,EAAkB,CAACD,CAAD,CAAM0E,CAAN,CAAmB,CAC5C,IAAIC,EAAS,CAAA,CAAb,CACIC,EAAMhF,CAAAiF,KAAA,CAAa7E,CAAb,CAAkBA,CAAA4B,KAAlB,CACV,OAAO,OACEU,QAAQ,CAACtB,CAAD,CAAMa,CAAN,CAAaV,CAAb,CAAmB,CAChCH,CAAA,CAAMpB,CAAAwB,UAAA,CAAkBJ,CAAlB,CACD2D,EAAAA,CAAL,EAAehC,CAAA,CAAgB3B,CAAhB,CAAf,GACE2D,CADF,CACW3D,CADX,CAGK2D,EAAL,EAAsC,CAAA,CAAtC,GAAeG,CAAA,CAAc9D,CAAd,CAAf,GACE4D,CAAA,CAAI,GAAJ,CAcA,CAbAA,CAAA,CAAI5D,CAAJ,CAaA,CAZApB,CAAAmF,QAAA,CAAgBlD,CAAhB,CAAuB,QAAQ,CAAC+B,CAAD,CAAQoB,CAAR,CAAY,CACzC,IAAIC,EAAKrF,CAAAwB,UAAA,CAAkB4D,CAAlB,CAAT,CACIE,EAAmB,KAAnBA,GAAWlE,CAAXkE,EAAqC,KAArCA,GAA4BD,CAA5BC,EAAyD,YAAzDA,GAAgDD,CAC3B,EAAA,CAAzB,GAAIE,CAAA,CAAWF,CAAX,CAAJ,EACsB,CAAA,CADtB,GACGG,CAAA,CAASH,CAAT,CADH,EAC8B,CAAAP,CAAA,CAAad,CAAb,CAAoBsB,CAApB,CAD9B,GAEEN,CAAA,CAAI,GAAJ,CAIA,CAHAA,CAAA,CAAII,CAAJ,CAGA,CAFAJ,CAAA,CAAI,IAAJ,CAEA,CADAA,CAAA,CAAIL,CAAA,CAAeX,CAAf,CAAJ,CACA,CAAAgB,CAAA,CAAI,GAAJ,CANF,CAHyC,CAA3C,CAYA,CAAAA,CAAA,CAAIzD,CAAA,CAAQ,IAAR,CAAe,GAAnB,CAfF,CALgC,CAD7B,KAwBAqB,QAAQ,CAACxB,CAAD,CAAK,CACdA,CAAA,CAAMpB,CAAAwB,UAAA,CAAkBJ,CAAlB,CACD2D,EAAL,EAAsC,CAAA,CAAtC,GAAeG,CAAA,CAAc9D,CAAd,CAAf,GACE4D,CAAA,CAAI,IAAJ,CAEA,CADAA,CAAA,CAAI5D,CAAJ,CACA,CAAA4D,CAAA,CAAI,GAAJ,CAHF,CAKI5D,EAAJ,EAAW2D,CAAX,GACEA,CADF,CACW,CAAA,CADX,CAPc,CAxBb,OAmCE5E,QAAQ,CAACA,CAAD,CAAO,CACb4E,CAAL;AACEC,CAAA,CAAIL,CAAA,CAAexE,CAAf,CAAJ,CAFgB,CAnCjB,CAHqC,CAha9C,IAAI4D,EAAkB/D,CAAAyF,SAAA,CAAiB,WAAjB,CAAtB,CAwJI3B,EACG,4FAzJP,CA0JEF,EAAiB,2BA1JnB,CA2JEzB,EAAc,yEA3JhB,CA4JE0B,EAAmB,IA5JrB,CA6JEF,EAAyB,SA7J3B,CA8JER,EAAiB,qBA9JnB,CA+JEM,EAAiB,qBA/JnB,CAgKEL,EAAe,yBAhKjB,CAkKEwB,EAA0B,gBAlK5B,CA2KI7C,EAAetB,CAAA,CAAQ,wBAAR,CAIfiF,EAAAA,CAA8BjF,CAAA,CAAQ,gDAAR,CAC9BkF,EAAAA,CAA+BlF,CAAA,CAAQ,OAAR,CADnC,KAEIqB,EAAyB9B,CAAA4F,OAAA,CAAe,EAAf,CACeD,CADf,CAEeD,CAFf,CAF7B,CAOIjE,EAAgBzB,CAAA4F,OAAA,CAAe,EAAf,CAAmBF,CAAnB,CAAgDjF,CAAA,CAAQ,4KAAR,CAAhD,CAPpB;AAYImB,EAAiB5B,CAAA4F,OAAA,CAAe,EAAf,CAAmBD,CAAnB,CAAiDlF,CAAA,CAAQ,2JAAR,CAAjD,CAZrB,CAkBIsC,EAAkBtC,CAAA,CAAQ,cAAR,CAlBtB,CAoBIyE,EAAgBlF,CAAA4F,OAAA,CAAe,EAAf,CACe7D,CADf,CAEeN,CAFf,CAGeG,CAHf,CAIeE,CAJf,CApBpB,CA2BI0D,EAAW/E,CAAA,CAAQ,0CAAR,CA3Bf,CA4BI8E,EAAavF,CAAA4F,OAAA,CAAe,EAAf,CAAmBJ,CAAnB,CAA6B/E,CAAA,CAC1C,ySAD0C,CAA7B,CA5BjB;AA0LI8D,EAAUsB,QAAAC,cAAA,CAAuB,KAAvB,CA1Ld,CA2LI5B,EAAU,wBAsGdlE,EAAA+F,OAAA,CAAe,YAAf,CAA6B,EAA7B,CAAAC,SAAA,CAA0C,WAA1C,CA7UAC,QAA0B,EAAG,CAC3B,IAAAC,KAAA,CAAY,CAAC,eAAD,CAAkB,QAAQ,CAACC,CAAD,CAAgB,CACpD,MAAO,SAAQ,CAAClF,CAAD,CAAO,CACpB,IAAIb,EAAM,EACVY,EAAA,CAAWC,CAAX,CAAiBZ,CAAA,CAAmBD,CAAnB,CAAwB,QAAQ,CAACgG,CAAD,CAAMd,CAAN,CAAe,CAC9D,MAAO,CAAC,SAAA5B,KAAA,CAAeyC,CAAA,CAAcC,CAAd,CAAmBd,CAAnB,CAAf,CADsD,CAA/C,CAAjB,CAGA,OAAOlF,EAAAI,KAAA,CAAS,EAAT,CALa,CAD8B,CAA1C,CADe,CA6U7B,CAuGAR,EAAA+F,OAAA,CAAe,YAAf,CAAAM,OAAA,CAAoC,OAApC,CAA6C,CAAC,WAAD,CAAc,QAAQ,CAACC,CAAD,CAAY,CAAA,IACzEC,EACE,mEAFuE,CAGzEC,EAAgB,UAEpB,OAAO,SAAQ,CAACtD,CAAD,CAAOuD,CAAP,CAAe,CAoB5BC,QAASA,EAAO,CAACxD,CAAD,CAAO,CAChBA,CAAL,EAGAjC,CAAAe,KAAA,CAAU9B,CAAA,CAAagD,CAAb,CAAV,CAJqB,CAOvByD,QAASA,EAAO,CAACC,CAAD,CAAM1D,CAAN,CAAY,CAC1BjC,CAAAe,KAAA,CAAU,KAAV,CACIhC,EAAA6G,UAAA,CAAkBJ,CAAlB,CAAJ;CACExF,CAAAe,KAAA,CAAU,UAAV,CAEA,CADAf,CAAAe,KAAA,CAAUyE,CAAV,CACA,CAAAxF,CAAAe,KAAA,CAAU,IAAV,CAHF,CAKAf,EAAAe,KAAA,CAAU,QAAV,CACAf,EAAAe,KAAA,CAAU4E,CAAV,CACA3F,EAAAe,KAAA,CAAU,IAAV,CACA0E,EAAA,CAAQxD,CAAR,CACAjC,EAAAe,KAAA,CAAU,MAAV,CAX0B,CA1B5B,GAAI,CAACkB,CAAL,CAAW,MAAOA,EAMlB,KALA,IAAId,CAAJ,CACI0E,EAAM5D,CADV,CAEIjC,EAAO,EAFX,CAGI2F,CAHJ,CAII9F,CACJ,CAAQsB,CAAR,CAAgB0E,CAAA1E,MAAA,CAAUmE,CAAV,CAAhB,CAAA,CAEEK,CAMA,CANMxE,CAAA,CAAM,CAAN,CAMN,CAJIA,CAAA,CAAM,CAAN,CAIJ,EAJgBA,CAAA,CAAM,CAAN,CAIhB,GAJ0BwE,CAI1B,CAJgC,SAIhC,CAJ4CA,CAI5C,EAHA9F,CAGA,CAHIsB,CAAAS,MAGJ,CAFA6D,CAAA,CAAQI,CAAAC,OAAA,CAAW,CAAX,CAAcjG,CAAd,CAAR,CAEA,CADA6F,CAAA,CAAQC,CAAR,CAAaxE,CAAA,CAAM,CAAN,CAAAF,QAAA,CAAiBsE,CAAjB,CAAgC,EAAhC,CAAb,CACA,CAAAM,CAAA,CAAMA,CAAAtD,UAAA,CAAc1C,CAAd,CAAkBsB,CAAA,CAAM,CAAN,CAAArB,OAAlB,CAER2F,EAAA,CAAQI,CAAR,CACA,OAAOR,EAAA,CAAUrF,CAAAT,KAAA,CAAU,EAAV,CAAV,CAlBqB,CAL+C,CAAlC,CAA7C,CAzjBsC,CAArC,CAAA,CA0mBET,MA1mBF,CA0mBUA,MAAAC,QA1mBV;", "sources":["angular-sanitize.js"], -"names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","makeMap","str","obj","items","split","i","length","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","lowercase","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","stack.last","specialElements","RegExp","all","text","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","parts","spaceRe","exec","spaceBefore","spaceAfter","content","hiddenPre","innerHTML","textContent","innerText","encodeEntities","NON_ALPHANUMERIC_REGEXP","charCodeAt","uriValidator","ignore","out","bind","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","document","createElement","module","provider","$SanitizeProvider","$get","$$sanitizeUri","uri","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","target","addText","addLink","url","isDefined","raw","substr"] +"names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","makeMap","str","obj","items","split","i","length","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","lowercase","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","stack.last","specialElements","RegExp","all","text","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGIN_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","parts","spaceRe","exec","spaceBefore","spaceAfter","content","hiddenPre","innerHTML","textContent","innerText","encodeEntities","NON_ALPHANUMERIC_REGEXP","charCodeAt","uriValidator","ignore","out","bind","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","document","createElement","module","provider","$SanitizeProvider","$get","$$sanitizeUri","uri","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","target","addText","addLink","url","isDefined","raw","substr"] } \ No newline at end of file From 04583ac165cd775864e2ace38c5196c12ffc4ae8 Mon Sep 17 00:00:00 2001 From: Amjad M <amjad@codilar.com> Date: Sat, 19 May 2018 13:22:43 +0530 Subject: [PATCH 0926/2023] fixed Submitting search form (mini) with enter key fires event handlers bound by jquery twice --- app/code/Magento/Search/view/frontend/web/form-mini.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Search/view/frontend/web/form-mini.js b/app/code/Magento/Search/view/frontend/web/form-mini.js index de16305bbbe8d..c064aba86caf9 100644 --- a/app/code/Magento/Search/view/frontend/web/form-mini.js +++ b/app/code/Magento/Search/view/frontend/web/form-mini.js @@ -226,6 +226,7 @@ define([ case $.ui.keyCode.ENTER: this.searchForm.trigger('submit'); + e.preventDefault(); break; case $.ui.keyCode.DOWN: From eea948d095a6b42713372bc69774e035d9b058e2 Mon Sep 17 00:00:00 2001 From: Kishan <kishan.patadia@drcsystems.com> Date: Thu, 24 May 2018 12:01:34 +0530 Subject: [PATCH 0927/2023] Variant product image in sidebar wishlist block --- app/code/Magento/Wishlist/CustomerData/Wishlist.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/code/Magento/Wishlist/CustomerData/Wishlist.php b/app/code/Magento/Wishlist/CustomerData/Wishlist.php index 9583a83a39428..6abed36690864 100644 --- a/app/code/Magento/Wishlist/CustomerData/Wishlist.php +++ b/app/code/Magento/Wishlist/CustomerData/Wishlist.php @@ -149,6 +149,13 @@ protected function getItemData(\Magento\Wishlist\Model\Item $wishlistItem) */ protected function getImageData($product) { + /* Set variant product if it is configurable product. It will show variant product image in sidebar instead of configurable product image. */ + $simpleOption = $product->getCustomOption('simple_product'); + if ($simpleOption !== null) { + $optionProduct = $simpleOption->getProduct(); + $product = $optionProduct; + } + /** @var \Magento\Catalog\Helper\Image $helper */ $helper = $this->imageHelperFactory->create() ->init($product, 'wishlist_sidebar_block'); From fb913ad8e5bc90fafebb1f343fffec1a83bd82be Mon Sep 17 00:00:00 2001 From: kishanpatadia <patadiakishan@gmail.com> Date: Thu, 24 May 2018 13:39:14 +0530 Subject: [PATCH 0928/2023] Update Wishlist.php --- app/code/Magento/Wishlist/CustomerData/Wishlist.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/CustomerData/Wishlist.php b/app/code/Magento/Wishlist/CustomerData/Wishlist.php index 6abed36690864..50a5259f76c44 100644 --- a/app/code/Magento/Wishlist/CustomerData/Wishlist.php +++ b/app/code/Magento/Wishlist/CustomerData/Wishlist.php @@ -149,7 +149,8 @@ protected function getItemData(\Magento\Wishlist\Model\Item $wishlistItem) */ protected function getImageData($product) { - /* Set variant product if it is configurable product. It will show variant product image in sidebar instead of configurable product image. */ + /*Set variant product if it is configurable product. + It will show variant product image in sidebar instead of configurable product image.*/ $simpleOption = $product->getCustomOption('simple_product'); if ($simpleOption !== null) { $optionProduct = $simpleOption->getProduct(); From 09459f6f92b800a8e3de7b91077592e587271df2 Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun <mitry@atwix.com> Date: Sun, 3 Jun 2018 10:28:54 +0300 Subject: [PATCH 0929/2023] Fix HTML syntax in report.phtml error template --- pub/errors/default/report.phtml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pub/errors/default/report.phtml b/pub/errors/default/report.phtml index f907e73149d41..546b96605ec1b 100644 --- a/pub/errors/default/report.phtml +++ b/pub/errors/default/report.phtml @@ -36,25 +36,25 @@ </div> <div class="field lastname required"> <label for="lastname" class="label">Last Name</label> - <div class=control"> + <div class="control"> <input type="text" name="lastname" id="lastname" value="<?= $this->postData['lastName'] ?>" title="Last Name" class="required-entry input-text" /> </div> </div> <div class="field email required"> <label for="email_address" class="label">Email Address</label> - <div class=control"> + <div class="control"> <input type="text" name="email" id="email_address" value="<?= $this->postData['email'] ?>" title="Email Address" class="validate-email required-entry input-text" /> </div> </div> <div class="field telephone"> <label for="telephone" class="label">Telephone</label> - <div class=control"> + <div class="control"> <input type="text" name="telephone" id="telephone" value="<?= $this->postData['telephone'] ?>" title="Telephone" class="input-text" /> </div> </div> <div class="field comment"> <label for="comment" class="label">Comment</label> - <div class=control"> + <div class="control"> <textarea name="comment" cols="5" rows="3" class="textarea"><?= $this->postData['comment'] ?></textarea> </div> </div> From 1ad9c5c183fb1e27e4c4a3de450bb1f687cece5e Mon Sep 17 00:00:00 2001 From: saurabh-aureate <saurabh.parekh@aureatelabs.com> Date: Mon, 28 May 2018 15:52:37 +0530 Subject: [PATCH 0930/2023] Remove extra space from trnslation file --- app/code/Magento/Captcha/i18n/en_US.csv | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/code/Magento/Captcha/i18n/en_US.csv b/app/code/Magento/Captcha/i18n/en_US.csv index 3c56d3f0d393d..480107df8adfe 100644 --- a/app/code/Magento/Captcha/i18n/en_US.csv +++ b/app/code/Magento/Captcha/i18n/en_US.csv @@ -20,11 +20,7 @@ Forms,Forms "Number of Symbols","Number of Symbols" "Please specify 8 symbols at the most. Range allowed (e.g. 3-5)","Please specify 8 symbols at the most. Range allowed (e.g. 3-5)" "Symbols Used in CAPTCHA","Symbols Used in CAPTCHA" -" - Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.<br />Similar looking characters (e.g. ""i"", ""l"", ""1"") decrease chance of correct recognition by customer. - "," - Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.<br />Similar looking characters (e.g. ""i"", ""l"", ""1"") decrease chance of correct recognition by customer. - " +"Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.<br />Similar looking characters (e.g. ""i"", ""l"", ""1"") decrease chance of correct recognition by customer.","Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.<br />Similar looking characters (e.g. ""i"", ""l"", ""1"") decrease chance of correct recognition by customer." "Case Sensitive","Case Sensitive" "Enable CAPTCHA on Storefront","Enable CAPTCHA on Storefront" "CAPTCHA for ""Create user"" and ""Forgot password"" forms is always enabled if chosen.","CAPTCHA for ""Create user"" and ""Forgot password"" forms is always enabled if chosen." From 6301ed4e968ca617aef8424a5d322446859ce2e7 Mon Sep 17 00:00:00 2001 From: Julien ANQUETIL <julien.anquetil@gmail.com> Date: Sun, 3 Jun 2018 09:49:47 +0200 Subject: [PATCH 0931/2023] [Forwardport] Fix #13415 : Duplicated elements id --- .../view/frontend/web/template/gift-message-form.html | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-form.html b/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-form.html index 20739f621ecff..15a36cc0e977a 100644 --- a/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-form.html +++ b/app/code/Magento/GiftMessage/view/frontend/web/template/gift-message-form.html @@ -12,26 +12,24 @@ <div class="gift-options-content"> <fieldset class="fieldset"> <div class="field field-to"> - <label for="gift-message-whole-to" class="label"> + <label data-bind="attr: {for: 'gift-message-whole-to-' + index }" class="label"> <span data-bind="i18n: 'To:'"></span> </label> <div class="control"> <input type="text" - id="gift-message-whole-to" class="input-text" - data-bind="value: getObservable('recipient')"> + data-bind="value: getObservable('recipient'), attr: { id: 'gift-message-whole-to-' + index }"> </div> </div> <div class="field field-from"> - <label for="gift-message-whole-from" class="label"> + <label data-bind="attr: {for: 'gift-message-whole-from-' + index }" class="label"> <span data-bind="i18n: 'From:'"></span> </label> <div class="control"> <input type="text" - id="gift-message-whole-from" class="input-text" - data-bind="value: getObservable('sender')"> + data-bind="value: getObservable('sender'), attr: { id: 'gift-message-whole-from-' + index }"> </div> </div> <div class="field text"> @@ -46,7 +44,6 @@ </div> </div> </fieldset> - </div> </div> <!-- /ko --> From 83b35872de163a43a6272402810d0b12cd3417b5 Mon Sep 17 00:00:00 2001 From: saurabh-aureate <saurabh.parekh@aureatelabs.com> Date: Fri, 25 May 2018 17:26:19 +0530 Subject: [PATCH 0932/2023] Use stored value of method instead of calling same method again. --- .../Magento/Directory/view/frontend/templates/currency.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Directory/view/frontend/templates/currency.phtml b/app/code/Magento/Directory/view/frontend/templates/currency.phtml index 30283effe4bb7..c01abca183d6a 100644 --- a/app/code/Magento/Directory/view/frontend/templates/currency.phtml +++ b/app/code/Magento/Directory/view/frontend/templates/currency.phtml @@ -24,7 +24,7 @@ data-mage-init='{"dropdown":{}}' data-toggle="dropdown" data-trigger-keypress-button="true"> - <strong class="language-<?= $block->escapeHtml($block->getCurrentCurrencyCode()) ?>"> + <strong class="language-<?= $block->escapeHtml($currentCurrencyCode) ?>"> <span><?= $block->escapeHtml($currentCurrencyCode) ?> - <?= @$block->escapeHtml($currencies[$currentCurrencyCode]) ?></span> </strong> </div> From 82d254b333920d275012105db915620190b7f9fa Mon Sep 17 00:00:00 2001 From: saurabh-aureate <saurabh.parekh@aureatelabs.com> Date: Fri, 25 May 2018 17:40:12 +0530 Subject: [PATCH 0933/2023] Use stored value of method instead of calling same method again. --- .../Magento/Marketplace/view/adminhtml/templates/partners.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Marketplace/view/adminhtml/templates/partners.phtml b/app/code/Magento/Marketplace/view/adminhtml/templates/partners.phtml index 309df6f883a49..b63bf9ebd50eb 100644 --- a/app/code/Magento/Marketplace/view/adminhtml/templates/partners.phtml +++ b/app/code/Magento/Marketplace/view/adminhtml/templates/partners.phtml @@ -11,7 +11,7 @@ $partners = $block->getPartners(); ?> <?php if ($partners) : ?> - <?php foreach ($block->getPartners() as $partner) : ?> + <?php foreach ($partners as $partner) : ?> <div class="partner"> <img class="partner-image" From 42f3f2eb1474b1eefc3cce150ce6800f6b648af7 Mon Sep 17 00:00:00 2001 From: saurabh-aureate <saurabh.parekh@aureatelabs.com> Date: Fri, 25 May 2018 19:06:09 +0530 Subject: [PATCH 0934/2023] Revert "Use stored value of method instead of calling same method again." This reverts commit cf9b1690b13a1698273bbc444720588040acc576. --- .../Magento/Directory/view/frontend/templates/currency.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Directory/view/frontend/templates/currency.phtml b/app/code/Magento/Directory/view/frontend/templates/currency.phtml index c01abca183d6a..30283effe4bb7 100644 --- a/app/code/Magento/Directory/view/frontend/templates/currency.phtml +++ b/app/code/Magento/Directory/view/frontend/templates/currency.phtml @@ -24,7 +24,7 @@ data-mage-init='{"dropdown":{}}' data-toggle="dropdown" data-trigger-keypress-button="true"> - <strong class="language-<?= $block->escapeHtml($currentCurrencyCode) ?>"> + <strong class="language-<?= $block->escapeHtml($block->getCurrentCurrencyCode()) ?>"> <span><?= $block->escapeHtml($currentCurrencyCode) ?> - <?= @$block->escapeHtml($currencies[$currentCurrencyCode]) ?></span> </strong> </div> From 31e49bcd0c2d5bb0a743e0c462ef62230b153f20 Mon Sep 17 00:00:00 2001 From: saurabh-aureate <saurabh.parekh@aureatelabs.com> Date: Fri, 25 May 2018 18:22:29 +0530 Subject: [PATCH 0935/2023] Typo correction --- app/code/Magento/Catalog/Model/Product/Type/AbstractType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php index 0ab1fbab471e6..d3f0c8be6f649 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php +++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php @@ -252,7 +252,7 @@ public function getChildrenIds($parentId, $required = true) } /** - * Retrieve parent ids array by requered child + * Retrieve parent ids array by required child * * @param int|array $childId * @return array From 14bf8af3db1683cbf4aeb5ca5924d8fd119e6d5a Mon Sep 17 00:00:00 2001 From: hitesh-wagento <hitesh@wagento.com> Date: Fri, 1 Jun 2018 11:28:21 +0530 Subject: [PATCH 0936/2023] --- lib/web/css/source/lib/_navigation.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/web/css/source/lib/_navigation.less b/lib/web/css/source/lib/_navigation.less index 6ed3a9671ab13..56aa2e7ef86b9 100644 --- a/lib/web/css/source/lib/_navigation.less +++ b/lib/web/css/source/lib/_navigation.less @@ -305,6 +305,10 @@ .lib-css(border-top, none); } + li.level1 { + position: relative; + } + .level0 { .lib-css(margin, @_nav-level0-item-margin); display: inline-block; From b2fd3436e33b9666cd193969bd577a61f7c1e117 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sun, 3 Jun 2018 12:34:30 +0200 Subject: [PATCH 0937/2023] Fixed return type of getImageData --- app/code/Magento/Wishlist/CustomerData/Wishlist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/CustomerData/Wishlist.php b/app/code/Magento/Wishlist/CustomerData/Wishlist.php index 9583a83a39428..85aff60ac6370 100644 --- a/app/code/Magento/Wishlist/CustomerData/Wishlist.php +++ b/app/code/Magento/Wishlist/CustomerData/Wishlist.php @@ -144,7 +144,7 @@ protected function getItemData(\Magento\Wishlist\Model\Item $wishlistItem) * Retrieve product image data * * @param \Magento\Catalog\Model\Product $product - * @return \Magento\Catalog\Block\Product\Image + * @return array * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function getImageData($product) From ce176d2ab2ae16790f84c7d6836afb51b4d9060a Mon Sep 17 00:00:00 2001 From: Sanjay Patel <sanjay@wagento.com> Date: Wed, 3 Jan 2018 14:30:23 +0530 Subject: [PATCH 0938/2023] #12601 - A space between the category page and the main footer when applying specific settings --- .../blank/Magento_Catalog/web/css/source/_module.less | 10 ++++++++++ .../luma/Magento_Catalog/web/css/source/_module.less | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less index 2dd8463308a2c..08a9b61977922 100644 --- a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less @@ -507,6 +507,16 @@ } } + // + // Category page 1 column layout + // --------------------------------------------- + + .catalog-category-view.page-layout-1column { + .column.main { + min-height: inherit; + } + } + } // diff --git a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less index 6f7da202c16e6..0d0434884f00d 100644 --- a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less @@ -742,6 +742,16 @@ } } } + + // + // Category page 1 column layout + // --------------------------------------------- + + .catalog-category-view.page-layout-1column { + .column.main { + min-height: inherit; + } + } } // From eaa585d36791c5ddb7073f0c7332f9c06f238bba Mon Sep 17 00:00:00 2001 From: amittiwari024 <amit.tiwari@aureatelabs.com> Date: Sat, 19 May 2018 14:38:56 +0530 Subject: [PATCH 0939/2023] Refactor javascript code of button split widget --- .../adminhtml/templates/widget/button/split.phtml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Backend/view/adminhtml/templates/widget/button/split.phtml b/app/code/Magento/Backend/view/adminhtml/templates/widget/button/split.phtml index 27127e54e5be2..a115777624e91 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/widget/button/split.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/widget/button/split.phtml @@ -41,11 +41,11 @@ <?php endif; ?> </div> -<script> -require(['jquery'], function($){ - $('.actions-split') - .on('click.splitDefault', '.action-default', function() { - $(this).siblings('.dropdown-menu').find('.item-default').trigger('click'); - }); -}); +<script type="text/x-magento-init"> + { + ".actions-split": { + "Magento_Ui/js/grid/controls/button/split": {} + } + } </script> + From 5822e4422213a4bacfccce41df3c8e87ccc7da1a Mon Sep 17 00:00:00 2001 From: neeta-wagento <neeta@wagento.com> Date: Sat, 19 May 2018 14:26:44 +0530 Subject: [PATCH 0940/2023] resolve non-unique elements id in console error --- .../view/frontend/web/template/billing-address/form.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html index 1be754934042b..00f87d325d963 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html @@ -9,7 +9,7 @@ <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> <form data-bind="attr: {'data-hasrequired': $t('* Required Fields')}"> - <fieldset id="billing-new-address-form" class="fieldset address"> + <fieldset data-bind="attr: { id:'billing-new-address-form-'+index, value:index}" class="fieldset address"> <!-- ko foreach: getRegion('additional-fieldsets') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> @@ -21,6 +21,6 @@ </label> </div> <!-- /ko --> - </fieldset> + </fieldset > </form> </div> From 4847b463a6e1305636f99455de45f296840ee979 Mon Sep 17 00:00:00 2001 From: Vishal Gelani <vishalgelani99@gmail.com> Date: Sat, 19 May 2018 14:36:20 +0530 Subject: [PATCH 0941/2023] Removed extra space. --- .../view/frontend/web/template/billing-address/form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html index 00f87d325d963..1568045d4a98e 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html @@ -21,6 +21,6 @@ </label> </div> <!-- /ko --> - </fieldset > + </fieldset> </form> </div> From a9f5a1d180c6ffe601c5ad95ad6475e75448383e Mon Sep 17 00:00:00 2001 From: Daniel Ruf <daniel.ruf@ueberbit.de> Date: Thu, 17 May 2018 18:20:52 +0200 Subject: [PATCH 0942/2023] fix: support multiple minisearch widget instances --- app/code/Magento/Search/view/frontend/web/form-mini.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Search/view/frontend/web/form-mini.js b/app/code/Magento/Search/view/frontend/web/form-mini.js index de16305bbbe8d..3ab44c2595de9 100644 --- a/app/code/Magento/Search/view/frontend/web/form-mini.js +++ b/app/code/Magento/Search/view/frontend/web/form-mini.js @@ -55,7 +55,7 @@ define([ this.autoComplete = $(this.options.destinationSelector); this.searchForm = $(this.options.formSelector); this.submitBtn = this.searchForm.find(this.options.submitBtn)[0]; - this.searchLabel = $(this.options.searchLabel); + this.searchLabel = this.searchForm.find(this.options.searchLabel); this.isExpandable = this.options.isExpandable; _.bindAll(this, '_onKeyDown', '_onPropertyChange', '_onSubmit'); From 52add61eb3468dff201eb189050aa3b73e03afbc Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Mon, 4 Jun 2018 10:17:19 +0300 Subject: [PATCH 0943/2023] MAGETWO-90370: Automate with MFTF Gift Options --- .../Section/CheckoutCartProductSection.xml | 9 ------ .../Checkout/Section/CheckoutCartSection.xml | 29 ------------------- .../Section/CheckoutCartSummarySection.xml | 2 -- 3 files changed, 40 deletions(-) delete mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSection.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml index 8364fd0e5783f..92c10ca83a76d 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartProductSection.xml @@ -26,14 +26,5 @@ parameterized="true"/> <element name="RemoveItem" type="button" selector="//table[@id='shopping-cart-table']//tbody//tr[contains(@class,'item-actions')]//a[contains(@class,'action-delete')]"/> - <element name="cartItemGiftOption" type="text" selector="//tr[contains(., '{{var1}}')]/following-sibling::*[contains(., '{{var2}}')]" parameterized="true"/> - <element name="cartGiftOptionAll" type="text" selector="//div[contains(@class,'cart-gift-item')][contains(., '{{var1}}')]" parameterized="true"/> - <element name="clickCartItemGiftOptions" type="button" selector=".gift-options-cart-item .action-gift"/> - <element name="clickCartGiftOptions" type="button" selector=".cart-gift-item div[data-role='title']"/> - <element name="cartVisibleSmallImage" type="text" selector=".gift-item-block .gift-options-content img"/> - <element name="cartItemVisibleSmallImage" type="text" selector="#shopping-cart-table .gift-options-content img"/> - <element name="cartGiftMessage" type="block" selector=".cart-gift-item .gift-message"/> - <element name="cartItemGiftMessage" type="block" selector="#shopping-cart-table .gift-options .gift-message"/> - <element name="cartItemClickButtonGiftUpdate" type="button" selector=".gift-options-cart-item button[type='submit']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSection.xml deleted file mode 100644 index 77867fb3b6d01..0000000000000 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSection.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> - <section name="CheckoutCartSection"> - <element name="giftWrappingName" type="text" selector=".gift-wrapping-name"/> - <element name="giftWrappingReqularPrice" type="text" selector=".gift-wrapping-title .regular-price span"/> - <element name="giftRemoveButton" type="button" selector=".gift-wrapping-title .action-remove"/> - <element name="clickImage" type="text" selector=".gift-wrapping-preview"/> - <element name="clickButtonGiftUpdate" type="button" selector=".cart-gift-item .actions-toolbar button[type='submit']"/> - <element name="giftWrapping" type="text" selector="//*[@id='cart-totals']//tr[@class='totals giftwrapping']//td[@class='amount']"/> - <element name="giftReceipt" type="text" selector=".gift-receipt label span"/> - <element name="giftReceiptCheckbox" type="checkbox" selector=".gift-receipt input"/> - <element name="giftPrintedCardCheckbox" type="checkbox" selector=".gift-printed-card input"/> - <element name="giftMessageTo" type="input" selector=".cart-gift-item .gift-message .gift-options-content .field-to input"/> - <element name="giftMessageFrom" type="input" selector=".cart-gift-item .gift-message .gift-options-content .field-from input"/> - <element name="giftMessage" type="textarea" selector=".cart-gift-item .gift-message .gift-options-content .text textarea"/> - <element name="giftWrappingNameResult" type="text" selector=".gift-summary .gift-wrapping-summary .gift-wrapping-name"/> - <element name="giftWrappingPriceResult" type="text" selector="//*[contains(., '{{var1}}')]/../span[@class='regular-price']//span[contains(., '{{var2}}')]" parameterized="true"/> - <element name="giftReceiptResult" type="text" selector=".gift-wrapping-summary span.label"/> - <element name="giftMessageResult" type="text" selector=".gift-message-summary"/> - </section> -</sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml index c4215649c587e..df236692d0d68 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml @@ -14,7 +14,5 @@ <element name="shipping" type="text" selector="//*[@id='cart-totals']//tr[@class='totals shipping excl']//td//span[@class='price']"/> <element name="total" type="text" selector="//*[@id='cart-totals']//tr[@class='grand totals']//td//span[@class='price']"/> <element name="proceedToCheckout" type="button" selector=".action.primary.checkout span" timeout="30"/> - <element name="giftWrappingOrderPrice" type="text" selector="#cart-totals td[data-th='Gift Wrapping for Order']"/> - <element name="giftPrintedCardPrice" type="text" selector="#cart-totals td[data-th='Printed Card']"/> </section> </sections> From 31cbafe3f571c9f876d20d4421d64e078a22beec Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Mon, 4 Jun 2018 10:17:41 +0300 Subject: [PATCH 0944/2023] MAGETWO-91807: Error when adding a product to the cart in the backend with the capitalization of the sku --- app/code/Magento/Catalog/Model/ProductRepository.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index a75e5349baa30..03ddab3d44547 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -809,9 +809,6 @@ private function getCollectionProcessor() private function getProductFromLocalCache(string $sku, string $cacheKey) { $preparedSku = $this->prepareSku($sku); - if (!isset($this->instances[$preparedSku])) { - return null; - } return $this->instances[$preparedSku][$cacheKey] ?? null; } From a5534bc8e748bd5da6c1700a03feee1346e416da Mon Sep 17 00:00:00 2001 From: Stas Puga <stas.puga@transoftgroup.com> Date: Mon, 4 Jun 2018 11:38:10 +0300 Subject: [PATCH 0945/2023] MAGETWO-90370: Automate with MFTF Gift Options --- .../Magento/FunctionalTest/Checkout/Page/CheckoutCartPage.xml | 1 - .../Magento/FunctionalTest/Sales/Page/AdminOrderDetailsPage.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Page/CheckoutCartPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Page/CheckoutCartPage.xml index 2e72571f15a2b..30e9bb0c95796 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Page/CheckoutCartPage.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Page/CheckoutCartPage.xml @@ -11,6 +11,5 @@ <page name="CheckoutCartPage" url="/checkout/cart" module="Checkout" area="storefront"> <section name="CheckoutCartProductSection"/> <section name="CheckoutCartSummarySection"/> - <section name="CheckoutCartSection"/> </page> </pages> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Page/AdminOrderDetailsPage.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Page/AdminOrderDetailsPage.xml index 0c8338b898670..df8f4ed63787c 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Page/AdminOrderDetailsPage.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Page/AdminOrderDetailsPage.xml @@ -22,6 +22,5 @@ <section name="AdminOrderShipmentsTabSection"/> <section name="AdminOrderCommentsTabSection"/> <section name="AdminOrderTotalSection"/> - <section name="AdminOrderGiftOptionSection"/> </page> </pages> \ No newline at end of file From 7f34b221d692f9bda0b3d6c9d17c76bd65cad30a Mon Sep 17 00:00:00 2001 From: Maikel Martens <maikel_martens_1@hotmail.com> Date: Wed, 30 May 2018 08:53:22 +0200 Subject: [PATCH 0946/2023] #15564 Generated admin API token expires immediately When admin token lifetime setting is empty, the token will expire immediatly --- .../Magento/Webapi/Model/Authorization/TokenUserContext.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/Webapi/Model/Authorization/TokenUserContext.php b/app/code/Magento/Webapi/Model/Authorization/TokenUserContext.php index 94196c9b86534..1b63b8c78e0b1 100644 --- a/app/code/Magento/Webapi/Model/Authorization/TokenUserContext.php +++ b/app/code/Magento/Webapi/Model/Authorization/TokenUserContext.php @@ -132,6 +132,11 @@ private function isTokenExpired(Token $token): bool // other user-type tokens are considered always valid return false; } + + if (empty($tokenTtl)) { + return false; + } + if ($this->dateTime->strToTime($token->getCreatedAt()) < ($this->date->gmtTimestamp() - $tokenTtl * 3600)) { return true; } From 349d178ee84de6b458d8783c16cf30bb25d51dc5 Mon Sep 17 00:00:00 2001 From: Maikel Martens <maikel_martens_1@hotmail.com> Date: Wed, 30 May 2018 13:50:20 +0200 Subject: [PATCH 0947/2023] Remove tab --- .../Magento/Webapi/Model/Authorization/TokenUserContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Webapi/Model/Authorization/TokenUserContext.php b/app/code/Magento/Webapi/Model/Authorization/TokenUserContext.php index 1b63b8c78e0b1..d89513b50c9c5 100644 --- a/app/code/Magento/Webapi/Model/Authorization/TokenUserContext.php +++ b/app/code/Magento/Webapi/Model/Authorization/TokenUserContext.php @@ -134,7 +134,7 @@ private function isTokenExpired(Token $token): bool } if (empty($tokenTtl)) { - return false; + return false; } if ($this->dateTime->strToTime($token->getCreatedAt()) < ($this->date->gmtTimestamp() - $tokenTtl * 3600)) { From 6bc77cbcfb0d9fe49c682953f1c1b4048a1a81ac Mon Sep 17 00:00:00 2001 From: Anna Voelkl <voelkl@e-conomix.at> Date: Fri, 25 May 2018 11:21:14 +0200 Subject: [PATCH 0948/2023] art: Fix typo in method name --- .../Magento/Multishipping/Block/Checkout/Overview.php | 11 ++++++++++- .../view/frontend/templates/checkout/overview.phtml | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Multishipping/Block/Checkout/Overview.php b/app/code/Magento/Multishipping/Block/Checkout/Overview.php index 2197598489358..f44eae0a04ab8 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/Overview.php +++ b/app/code/Magento/Multishipping/Block/Checkout/Overview.php @@ -319,9 +319,18 @@ public function getQuote() } /** - * @return mixed + * @deprecated + * typo in method name, see getBillingAddressTotals() */ public function getBillinAddressTotals() + { + return $this->getBillingAddressTotals(); + } + + /** + * @return mixed + */ + public function getBillingAddressTotals() { $address = $this->getQuote()->getBillingAddress(); return $this->getShippingAddressTotals($address); diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/overview.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/overview.phtml index d4d446a7567db..4590b7c584085 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/overview.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/overview.phtml @@ -186,7 +186,7 @@ <?php endforeach; ?> </tbody> <tfoot> - <?= /* @noEscape */ $block->renderTotals($block->getBillinAddressTotals()); ?> + <?= /* @noEscape */ $block->renderTotals($block->getBillingAddressTotals()); ?> </tfoot> </table> </div> From c494d735a94feb7db8527bf9df994a82baa0e9c8 Mon Sep 17 00:00:00 2001 From: Anna Voelkl <voelkl@e-conomix.at> Date: Fri, 25 May 2018 15:47:25 +0200 Subject: [PATCH 0949/2023] Revert ":pencil2: Fix typos in Multishipping and User module" This reverts commit aa96d022adeff10ad42ab782ca7abb3233f1718d. --- .../Multishipping/Block/Checkout/AbstractMultishipping.php | 2 +- app/code/Magento/Multishipping/Block/Checkout/Shipping.php | 2 +- app/code/Magento/User/Model/Backend/Config/ObserverConfig.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php b/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php index d3c17a8d7c8de..0de66ccd505a4 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php +++ b/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php @@ -5,7 +5,7 @@ */ /** - * Multishipping checkout base abstract block + * Mustishipping checkout base abstract block * * @author Magento Core Team <core@magentocommerce.com> */ diff --git a/app/code/Magento/Multishipping/Block/Checkout/Shipping.php b/app/code/Magento/Multishipping/Block/Checkout/Shipping.php index ef1aa6301b23d..77981c736b9e9 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/Shipping.php +++ b/app/code/Magento/Multishipping/Block/Checkout/Shipping.php @@ -9,7 +9,7 @@ use Magento\Quote\Model\Quote\Address; /** - * Multishipping checkout shipping + * Mustishipping checkout shipping * * @api * @author Magento Core Team <core@magentocommerce.com> diff --git a/app/code/Magento/User/Model/Backend/Config/ObserverConfig.php b/app/code/Magento/User/Model/Backend/Config/ObserverConfig.php index 6d921dfdcdd65..c1b7e6a1110f7 100644 --- a/app/code/Magento/User/Model/Backend/Config/ObserverConfig.php +++ b/app/code/Magento/User/Model/Backend/Config/ObserverConfig.php @@ -72,7 +72,7 @@ public function getAdminPasswordLifetime() } /** - * Get admin maximum security failures from config + * Get admin maxiumum security failures from config * * @return int */ From 6e2dea6436ec61ff14e82371bb0456e2450632db Mon Sep 17 00:00:00 2001 From: Anna Voelkl <voelkl@e-conomix.at> Date: Fri, 25 May 2018 15:49:25 +0200 Subject: [PATCH 0950/2023] bug: Add phpdoc return type --- app/code/Magento/Multishipping/Block/Checkout/Overview.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Multishipping/Block/Checkout/Overview.php b/app/code/Magento/Multishipping/Block/Checkout/Overview.php index f44eae0a04ab8..c77fadfd2d4f1 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/Overview.php +++ b/app/code/Magento/Multishipping/Block/Checkout/Overview.php @@ -321,6 +321,7 @@ public function getQuote() /** * @deprecated * typo in method name, see getBillingAddressTotals() + * @return mixed */ public function getBillinAddressTotals() { From 9850d9c3444322e9005f9446ae63e7e901ea3e77 Mon Sep 17 00:00:00 2001 From: David Manners <dmanners87@gmail.com> Date: Fri, 25 May 2018 16:08:38 +0200 Subject: [PATCH 0951/2023] Remove unneeded white space --- app/code/Magento/Multishipping/Block/Checkout/Overview.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/Block/Checkout/Overview.php b/app/code/Magento/Multishipping/Block/Checkout/Overview.php index c77fadfd2d4f1..5963e62e948f9 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/Overview.php +++ b/app/code/Magento/Multishipping/Block/Checkout/Overview.php @@ -321,7 +321,7 @@ public function getQuote() /** * @deprecated * typo in method name, see getBillingAddressTotals() - * @return mixed + * @return mixed */ public function getBillinAddressTotals() { From 365bfb4c81914041d063d99b3a87fe8d96fcc6c9 Mon Sep 17 00:00:00 2001 From: hitesh-wagento <hitesh@wagento.com> Date: Wed, 23 May 2018 15:41:52 +0530 Subject: [PATCH 0952/2023] --- .../backend/Magento_Ui/web/css/source/module/_data-grid.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less index 9480161248d15..0c2d6ad8786ca 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less @@ -304,7 +304,7 @@ body._in-resize { .action-menu { left: auto; min-width: 10rem; - right: auto; + right: 0; text-align: left; top: auto; z-index: 1; From 6711694e180078c714f9216ac0b83cef74ac0a6f Mon Sep 17 00:00:00 2001 From: Nimesh Patel <patelnimesh1988@gmail.com> Date: Tue, 22 May 2018 14:48:04 +0530 Subject: [PATCH 0953/2023] Refactor JavsScript for UrlRewrite module edit page --- .../view/adminhtml/templates/edit.phtml | 17 ++++++++--------- .../web/js/url-rewrite-validation.js | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 app/code/Magento/UrlRewrite/view/adminhtml/web/js/url-rewrite-validation.js diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/templates/edit.phtml b/app/code/Magento/UrlRewrite/view/adminhtml/templates/edit.phtml index 09ac4a5990f6b..3ff25a7c84521 100644 --- a/app/code/Magento/UrlRewrite/view/adminhtml/templates/edit.phtml +++ b/app/code/Magento/UrlRewrite/view/adminhtml/templates/edit.phtml @@ -10,14 +10,13 @@ ?> <?= $block->getChildHtml() ?> <?php if ($block->getChildBlock('form')): ?> -<script> -require([ - 'jquery', - 'mage/backend/form', - 'mage/backend/validation' -], function($){ - $('#edit_form').form() - .validation({validationUrl: '<?= $block->escapeUrl($block->getValidationUrl()) ?>'}); -}); +<script type="text/x-magento-init"> + { + "#edit_form": { + "Magento_UrlRewrite/js/url-rewrite-validation" : { + "url": "<?= $block->escapeUrl($block->getValidationUrl()) ?>" + } + } + } </script> <?php endif; ?> diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/web/js/url-rewrite-validation.js b/app/code/Magento/UrlRewrite/view/adminhtml/web/js/url-rewrite-validation.js new file mode 100644 index 0000000000000..548f712bacadd --- /dev/null +++ b/app/code/Magento/UrlRewrite/view/adminhtml/web/js/url-rewrite-validation.js @@ -0,0 +1,19 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'mage/backend/form', + 'mage/backend/validation' +], function ($) { + 'use strict'; + + return function (data, element) { + + $(element).form().validation({ + validationUrl: data.url + }); + }; +}); From 868c07765923faccf6b15b8f60ddb2eea74181d3 Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk <vova.yatsyuk@gmail.com> Date: Mon, 21 May 2018 17:18:22 +0300 Subject: [PATCH 0954/2023] Prevent multiple add-to-cart initializations in case of ajax loaded content --- .../Catalog/view/frontend/web/js/catalog-add-to-cart.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/Catalog/view/frontend/web/js/catalog-add-to-cart.js b/app/code/Magento/Catalog/view/frontend/web/js/catalog-add-to-cart.js index b2da91c3b55c1..8fcac2f9f1d65 100644 --- a/app/code/Magento/Catalog/view/frontend/web/js/catalog-add-to-cart.js +++ b/app/code/Magento/Catalog/view/frontend/web/js/catalog-add-to-cart.js @@ -38,6 +38,11 @@ define([ _bindSubmit: function () { var self = this; + if (this.element.data('catalog-addtocart-initialized')) { + return; + } + + this.element.data('catalog-addtocart-initialized', 1); this.element.on('submit', function (e) { e.preventDefault(); self.submitForm($(this)); From e7c3e29a1caca0be477250ad124fcf8a62f0e925 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 4 Jun 2018 12:26:53 +0300 Subject: [PATCH 0955/2023] MAGETWO-90808: [Performance] Customer Import check data does not complete --- .../Model/Import/Address.php | 17 ++-- .../Model/Import/Customer.php | 11 +-- .../Model/Import/CustomerComposite.php | 2 +- .../ResourceModel/Import/Address/Storage.php | 12 +-- .../ResourceModel/Import/Customer/Storage.php | 22 +++-- .../Test/Unit/Model/Import/AddressTest.php | 5 +- .../Model/Import/CustomerCompositeTest.php | 82 ++++++++----------- .../Test/Unit/Model/Import/CustomerTest.php | 2 +- .../Import/Customer/StorageTest.php | 25 +++--- 9 files changed, 78 insertions(+), 100 deletions(-) diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Address.php b/app/code/Magento/CustomerImportExport/Model/Import/Address.php index e3f1d68f8d1d5..adff4afc79b4e 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Address.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Address.php @@ -169,6 +169,9 @@ class Address extends AbstractCustomer protected $_attributeCollection; /** + * Collection of existent addresses + * + * @var \Magento\Customer\Model\ResourceModel\Address\Collection * @deprecated */ protected $_addressCollection; @@ -227,7 +230,7 @@ class Address extends AbstractCustomer protected $postcodeValidator; /** - * @deprecated + * @var CountryWithWebsitesSource */ private $countryWithWebsites; @@ -319,9 +322,6 @@ public function __construct( $data ); - $this->_addressCollection = isset( - $data['address_collection'] - ) ? $data['address_collection'] : $addressColFactory->create(); $this->_entityTable = isset( $data['entity_table'] ) ? $data['entity_table'] : $addressFactory->create()->getResource()->getEntityTable(); @@ -459,18 +459,17 @@ protected function _initCountryRegions() * * @return void */ - public function prepareCustomerData($rows) + public function prepareCustomerData($rows): void { $customersPresent = []; foreach ($rows as $rowData) { - $email = isset($rowData[static::COLUMN_EMAIL]) - ? $rowData[static::COLUMN_EMAIL] : null; + $email = $rowData[static::COLUMN_EMAIL] ?? null; $websiteId = isset($rowData[static::COLUMN_WEBSITE]) ? $this->getWebsiteId($rowData[static::COLUMN_WEBSITE]) : false; if ($email && $websiteId !== false) { $customersPresent[] = [ 'email' => $email, - 'website_id' => $websiteId + 'website_id' => $websiteId, ]; } } @@ -917,7 +916,7 @@ protected function _validateRowForDelete(array $rowData, $rowNumber) if (!strlen($addressId)) { $this->addRowError(self::ERROR_ADDRESS_ID_IS_EMPTY, $rowNumber); } elseif (!$this->addressStorage->doesExist( - $addressId, + (string)$addressId, (string)$customerId )) { $this->addRowError(self::ERROR_ADDRESS_NOT_FOUND, $rowNumber); diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php index a1aa62c5f1c89..e5cc543db6aac 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php @@ -347,26 +347,23 @@ protected function _getNextEntityId() } /** - * Pre-loading customers for existing customers checks in order - * to perform mass validation/import efficiently. + * Prepare customers data for existing customers checks to perform mass validation/import efficiently. * * @param array|AbstractSource $rows - * and website code. * * @return void */ - public function prepareCustomerData($rows) + public function prepareCustomerData($rows): void { $customersPresent = []; foreach ($rows as $rowData) { - $email = isset($rowData[static::COLUMN_EMAIL]) - ? $rowData[static::COLUMN_EMAIL] : null; + $email = $rowData[static::COLUMN_EMAIL] ?? null; $websiteId = isset($rowData[static::COLUMN_WEBSITE]) ? $this->getWebsiteId($rowData[static::COLUMN_WEBSITE]) : false; if ($email && $websiteId !== false) { $customersPresent[] = [ 'email' => $email, - 'website_id' => $websiteId + 'website_id' => $websiteId, ]; } } diff --git a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php index b2c82f13fc554..956c9695623bb 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php @@ -300,7 +300,7 @@ public function validateData() foreach ($source as $row) { $rows[] = [ Address::COLUMN_EMAIL => $row[Customer::COLUMN_EMAIL], - Address::COLUMN_WEBSITE => $row[Customer::COLUMN_WEBSITE] + Address::COLUMN_WEBSITE => $row[Customer::COLUMN_WEBSITE], ]; } $source->rewind(); diff --git a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Address/Storage.php b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Address/Storage.php index bb73c105055b6..6d29d7ae792ff 100644 --- a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Address/Storage.php +++ b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Address/Storage.php @@ -67,13 +67,11 @@ public function __construct( * * @return void */ - private function addRecord(string $customerId, string $addressId) + private function addRecord(string $customerId, string $addressId): void { if (!$customerId || !$addressId) { return; } - $customerId = (string)$customerId; - $addressId = (string)$addressId; if (!array_key_exists($customerId, $this->addresses)) { $this->addresses[$customerId] = []; } @@ -89,9 +87,8 @@ private function addRecord(string $customerId, string $addressId) * @param string[] $customerIds * * @return void - * @throws \Zend_Db_Select_Exception */ - private function loadAddresses(array $customerIds) + private function loadAddresses(array $customerIds): void { /** @var AddressCollection $collection */ $collection = $this->addressCollectionFactory->create(); @@ -122,7 +119,7 @@ public function doesExist(string $addressId, string $forCustomerId): bool { return array_key_exists($forCustomerId, $this->addresses) && in_array( - (string)$addressId, + $addressId, $this->addresses[$forCustomerId], true ); @@ -133,9 +130,8 @@ public function doesExist(string $addressId, string $forCustomerId): bool * * @param string[] $forCustomersIds * @return void - * @throws \Zend_Db_Select_Exception */ - public function prepareAddresses(array $forCustomersIds) + public function prepareAddresses(array $forCustomersIds): void { if (!$forCustomersIds) { return; diff --git a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php index dec8c0739213e..03c75297343c3 100644 --- a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php +++ b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php @@ -5,6 +5,7 @@ */ namespace Magento\CustomerImportExport\Model\ResourceModel\Import\Customer; +use Magento\CustomerImportExport\Test\Unit\Model\Import\CustomerCompositeTest; use Magento\Framework\DataObject; use Magento\Framework\DB\Select; use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory as CustomerCollectionFactory; @@ -15,11 +16,17 @@ class Storage { /** + * Flag to not load collection more than one time + * + * @var bool * @deprecated */ protected $_isCollectionLoaded = false; /** + * Customer collection + * + * @var \Magento\Customer\Model\ResourceModel\Customer\Collection * @deprecated */ protected $_customerCollection; @@ -78,8 +85,9 @@ public function __construct( } /** - * @return void + * Load needed data from customer collection * + * @return void * @deprecated * @see prepareCustomers */ @@ -104,7 +112,6 @@ public function load() * @param array[] $customerIdentifiers With keys "email" and "website_id". * * @return CustomerCollection - * @throws \Zend_Db_Select_Exception */ private function prepareCollection(array $customerIdentifiers): CustomerCollection { @@ -132,7 +139,6 @@ function (array $customer) { * @param array $customerIdentifiers With keys "email" and "website_id". * * @return void - * @throws \Zend_Db_Select_Exception */ private function loadCustomersData(array $customerIdentifiers) { @@ -147,7 +153,7 @@ private function loadCustomersData(array $customerIdentifiers) * @param array $customer * @return $this */ - public function addCustomerByArray(array $customer): self + public function addCustomerByArray(array $customer): Storage { $email = strtolower(trim($customer['email'])); if (!isset($this->_customerIds[$email])) { @@ -165,7 +171,7 @@ public function addCustomerByArray(array $customer): self * @param DataObject $customer * @return $this */ - public function addCustomer(DataObject $customer): self + public function addCustomer(DataObject $customer): Storage { $customerData = $customer->toArray(); if (!isset($customerData['entity_id']) && isset($customer['id'])) { @@ -182,7 +188,6 @@ public function addCustomer(DataObject $customer): self * @param string $email * @param int $websiteId * @return bool|int - * @throws \Zend_Db_Select_Exception */ public function getCustomerId(string $email, int $websiteId) { @@ -205,9 +210,8 @@ public function getCustomerId(string $email, int $websiteId) * * @param array[] $customersToFind With keys: email, website_id. * @return void - * @throws \Zend_Db_Select_Exception */ - public function prepareCustomers(array $customersToFind) + public function prepareCustomers(array $customersToFind): void { $identifiers = []; foreach ($customersToFind as $customerToFind) { @@ -221,7 +225,7 @@ public function prepareCustomers(array $customersToFind) $uniqueKey = $email .'_' .$websiteId; $identifiers[$uniqueKey] = [ 'email' => $email, - 'website_id' => $websiteId + 'website_id' => $websiteId, ]; //Recording that we've searched for a customer. if (!array_key_exists($email, $this->_customerIds)) { diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php index d96ebd9aca666..113d6fa06ba31 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php @@ -261,8 +261,8 @@ protected function _createCustomerStorageMock() ->willReturnCallback( function ($email, $websiteId) { foreach ($this->_customers as $customerData) { - if ($customerData['email'] == $email - && $customerData['website_id'] == $websiteId + if ($customerData['email'] === $email + && $customerData['website_id'] === $websiteId ) { return $customerData['entity_id']; } @@ -334,7 +334,6 @@ public function iterate(\Magento\Framework\Data\Collection $collection, $pageSiz * Create mock for custom behavior test * * @return Address|\PHPUnit_Framework_MockObject_MockObject - * @throws \ReflectionException */ protected function _getModelMockForTestImportDataWithCustomBehaviour() { diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php index c19f1ac9e38c9..983e20eb77d80 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php @@ -185,26 +185,26 @@ protected function _getModelMockForPrepareRowForDb() 'stdClass', ['getCustomerId', 'prepareCustomers', 'addCustomer'] ); - $customerStorage->expects($this->any())->method('getCustomerId')->will($this->returnValue(1)); + $customerStorage->expects($this->any())->method('getCustomerId')->willReturn(1); $customerEntity = $this->_getCustomerEntityMock(); - $customerEntity->expects($this->any())->method('validateRow')->will($this->returnValue(true)); + $customerEntity->expects($this->any())->method('validateRow')->willReturn(true); $customerEntity->expects($this->any()) ->method('getCustomerStorage') - ->will($this->returnValue($customerStorage)); + ->willReturn($customerStorage); $customerEntity->expects($this->any()) ->method('getValidColumnNames') ->willReturn(['cols']); $addressEntity = $this->_getAddressEntityMock(); - $addressEntity->expects($this->any())->method('validateRow')->will($this->returnValue(true)); + $addressEntity->expects($this->any())->method('validateRow')->willReturn(true); $addressEntity->expects($this->any()) ->method('getCustomerStorage') - ->will($this->returnValue($customerStorage)); + ->willReturn($customerStorage); $dataSourceMock = $this->createPartialMock(\stdClass::class, ['cleanBunches', 'saveBunch']); $dataSourceMock->expects($this->any()) ->method('saveBunch') - ->will($this->returnCallback([$this, 'verifyPrepareRowForDbData'])); + ->willReturnCallback([$this, 'verifyPrepareRowForDbData']); $data = $this->_getModelDependencies(); $data['customer_entity'] = $customerEntity; @@ -225,15 +225,15 @@ protected function _getModelMockForPrepareRowForDb() protected function _getModelMockForImportData($isDeleteBehavior, $customerImport, $addressImport) { $customerEntity = $this->_getCustomerEntityMock(); - $customerEntity->expects($this->once())->method('importData')->will($this->returnValue($customerImport)); + $customerEntity->expects($this->once())->method('importData')->willReturn($customerImport); $addressEntity = $this->_getAddressEntityMock(); // address import starts only if customer import finished successfully if ($isDeleteBehavior || !$customerImport) { $addressEntity->expects($this->never())->method('importData'); } else { - $addressEntity->expects($this->once())->method('setCustomerAttributes')->will($this->returnSelf()); - $addressEntity->expects($this->once())->method('importData')->will($this->returnValue($addressImport)); + $addressEntity->expects($this->once())->method('setCustomerAttributes')->willReturnSelf(); + $addressEntity->expects($this->once())->method('importData')->willReturn($addressImport); } $data = $this->_getModelDependencies(); @@ -255,13 +255,9 @@ protected function _getCustomerEntityMock() $attribute = new \Magento\Framework\DataObject(['attribute_code' => $code]); $attributeList[] = $attribute; } - $customerEntity->expects( - $this->once() - )->method( - 'getAttributeCollection' - )->will( - $this->returnValue($attributeList) - ); + $customerEntity->expects($this->once()) + ->method('getAttributeCollection') + ->willReturn($attributeList); return $customerEntity; } @@ -278,13 +274,9 @@ protected function _getAddressEntityMock() $attribute = new \Magento\Framework\DataObject(['attribute_code' => $code]); $attributeList[] = $attribute; } - $addressEntity->expects( - $this->once() - )->method( - 'getAttributeCollection' - )->will( - $this->returnValue($attributeList) - ); + $addressEntity->expects($this->once()) + ->method('getAttributeCollection') + ->willReturn($attributeList); return $addressEntity; } @@ -342,22 +334,22 @@ public function testValidateRow(array $rows, array $calls, $validationReturn, ar $customerEntity->expects($this->exactly($calls['customerValidationCalls'])) ->method('validateRow') - ->will($this->returnValue($validationReturn)); + ->willReturn($validationReturn); $addressEntity ->expects($this->exactly($calls['addressValidationCalls'])) ->method('validateRow') - ->will($this->returnValue($validationReturn)); + ->willReturn($validationReturn); $customerStorage = $this->createPartialMock(\stdClass::class, ['getCustomerId']); - $customerStorage->expects($this->any())->method('getCustomerId')->will($this->returnValue(true)); + $customerStorage->expects($this->any())->method('getCustomerId')->willReturn(true); $addressEntity->expects($this->any()) ->method('getCustomerStorage') - ->will($this->returnValue($customerStorage)); + ->willReturn($customerStorage); $customerEntity->expects($this->any()) ->method('getCustomerStorage') - ->will($this->returnValue($customerStorage)); + ->willReturn($customerStorage); $data = $this->_getModelDependencies(); $data['customer_entity'] = $customerEntity; @@ -379,20 +371,20 @@ public function testPrepareAddressRowData() $customerEntity = $this->_getCustomerEntityMock(); $addressEntity = $this->_getAddressEntityMock(); - $customerEntity->expects($this->once())->method('validateRow')->will($this->returnValue(true)); + $customerEntity->expects($this->once())->method('validateRow')->willReturn(true); $addressEntity->expects($this->once()) ->method('validateRow') - ->will($this->returnCallback([$this, 'validateAddressRowParams'])); + ->willReturnCallback([$this, 'validateAddressRowParams']); $customerStorage = $this->createPartialMock(\stdClass::class, ['getCustomerId']); - $customerStorage->expects($this->any())->method('getCustomerId')->will($this->returnValue(true)); + $customerStorage->expects($this->any())->method('getCustomerId')->willReturn(true); $addressEntity->expects($this->any()) ->method('getCustomerStorage') - ->will($this->returnValue($customerStorage)); + ->willReturn($customerStorage); $customerEntity->expects($this->any()) ->method('getCustomerStorage') - ->will($this->returnValue($customerStorage)); + ->willReturn($customerStorage); $data = $this->_getModelDependencies(); $data['customer_entity'] = $customerEntity; @@ -507,20 +499,12 @@ public function testSetParameters() $customerEntity = $this->_getCustomerEntityMock(); $addressEntity = $this->_getAddressEntityMock(); - $customerEntity->expects( - $this->once() - )->method( - 'setParameters' - )->will( - $this->returnCallback([$this, 'callbackCheckParameters']) - ); - $addressEntity->expects( - $this->once() - )->method( - 'setParameters' - )->will( - $this->returnCallback([$this, 'callbackCheckParameters']) - ); + $customerEntity->expects($this->once()) + ->method('setParameters') + ->willReturnCallback([$this, 'callbackCheckParameters']); + $addressEntity->expects($this->once()) + ->method('setParameters') + ->willReturnCallback([$this, 'callbackCheckParameters']); $data = $this->_getModelDependencies(); $data['customer_entity'] = $customerEntity; $data['address_entity'] = $addressEntity; @@ -686,8 +670,8 @@ protected function _getModelForGetterTest($method, $customerReturnData, $address $customerEntity = $this->_getCustomerEntityMock(); $addressEntity = $this->_getAddressEntityMock(); - $customerEntity->expects($this->once())->method($method)->will($this->returnValue($customerReturnData)); - $addressEntity->expects($this->once())->method($method)->will($this->returnValue($addressReturnData)); + $customerEntity->expects($this->once())->method($method)->willReturn($customerReturnData); + $addressEntity->expects($this->once())->method($method)->willReturn($addressReturnData); $data = $this->_getModelDependencies(); $data['customer_entity'] = $customerEntity; diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerTest.php index 64c547c0ae22b..9a7183d5b5f72 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerTest.php @@ -91,7 +91,7 @@ protected function _getModelMockForTestImportDataWithCustomBehaviour() '_saveCustomerAttributes', '_deleteCustomerEntities', 'getErrorAggregator', - 'getCustomerStorage' + 'getCustomerStorage', ] ) ->getMock(); diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/ResourceModel/Import/Customer/StorageTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/ResourceModel/Import/Customer/StorageTest.php index 90342f7817364..1f2f9f3fed583 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/ResourceModel/Import/Customer/StorageTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/ResourceModel/Import/Customer/StorageTest.php @@ -3,6 +3,10 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +/** + * Test class for \Magento\CustomerImportExport\Model\ResourceModel\Import\Customer\Storage + */ namespace Magento\CustomerImportExport\Test\Unit\Model\ResourceModel\Import\Customer; use Magento\CustomerImportExport\Model\ResourceModel\Import\Customer\Storage; @@ -18,7 +22,7 @@ class StorageTest extends \PHPUnit\Framework\TestCase /** * @var Storage */ - private $_model; + private $model; /** * @var CollectionByPagesIterator|\PHPUnit_Framework_MockObject_MockObject @@ -30,11 +34,6 @@ class StorageTest extends \PHPUnit\Framework\TestCase */ private $collectionMock; - /** - * @var string - */ - protected $_entityTable = 'test'; - protected function setUp() { $this->iteratorMock = $this->createMock( @@ -65,7 +64,7 @@ protected function setUp() ->method('getSelect') ->willReturn($selectMock); - $this->_model = new Storage( + $this->model = new Storage( $collectionFactoryMock, $iteratorFactoryMock, [] @@ -74,7 +73,7 @@ protected function setUp() protected function tearDown() { - unset($this->_model); + unset($this->model); } public function testAddCustomerByArray() @@ -82,9 +81,9 @@ public function testAddCustomerByArray() $propertyName = '_customerIds'; $customer = $this->_addCustomerToStorage(); - $this->assertAttributeCount(1, $propertyName, $this->_model); + $this->assertAttributeCount(1, $propertyName, $this->model); $expectedCustomerData = [$customer['website_id'] => $customer['entity_id']]; - $this->assertAttributeContains($expectedCustomerData, $propertyName, $this->_model); + $this->assertAttributeContains($expectedCustomerData, $propertyName, $this->model); } public function testGetCustomerId() @@ -117,10 +116,10 @@ function (...$args) use ( ); $this->assertEquals( $existingId, - $this->_model->getCustomerId($existingEmail, $existingWebsiteId) + $this->model->getCustomerId($existingEmail, $existingWebsiteId) ); $this->assertFalse( - $this->_model->getCustomerId( + $this->model->getCustomerId( $nonExistingEmail, $nonExistingWebsiteId ) @@ -133,7 +132,7 @@ function (...$args) use ( protected function _addCustomerToStorage() { $customer = ['entity_id' => 1, 'website_id' => 1, 'email' => 'test@test.com']; - $this->_model->addCustomerByArray($customer); + $this->model->addCustomerByArray($customer); return $customer; } From 3e21eddf6123b5397a2056a188bc223f61783d59 Mon Sep 17 00:00:00 2001 From: Rahul Kachhadiya <rbkachhadiya@gmail.com> Date: Sat, 19 May 2018 16:17:09 +0530 Subject: [PATCH 0956/2023] Added language translation in template files --- .../Braintree/view/adminhtml/templates/form/cc.phtml | 2 +- app/code/Magento/Multishipping/i18n/en_US.csv | 2 ++ .../view/frontend/templates/checkout/results.phtml | 6 +++--- .../view/frontend/templates/checkout/success.phtml | 2 +- .../Paypal/view/adminhtml/templates/transparent/form.phtml | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml index 13249cd8e0e80..535a5a852fe70 100644 --- a/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml +++ b/app/code/Magento/Braintree/view/adminhtml/templates/form/cc.phtml @@ -84,7 +84,7 @@ $ccType = $block->getInfoData('cc_type'); name="payment[is_active_payment_token_enabler]" class="admin__control-checkbox"/> <label class="label" for="<?= /* @noEscape */ $code ?>_vault"> - <span><?= $block->escapeHtml('Save for later use.') ?></span> + <span><?= $block->escapeHtml(__('Save for later use.')) ?></span> </label> </div> <?php endif; ?> diff --git a/app/code/Magento/Multishipping/i18n/en_US.csv b/app/code/Magento/Multishipping/i18n/en_US.csv index 1e3e1880758ee..43cc785c56eab 100644 --- a/app/code/Magento/Multishipping/i18n/en_US.csv +++ b/app/code/Magento/Multishipping/i18n/en_US.csv @@ -88,3 +88,5 @@ Options,Options "Review Order","Review Order" "Select Shipping Method","Select Shipping Method" "We received your order!","We received your order!" +"Ship to:","Ship to:" +"Error:","Error:" \ No newline at end of file diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/results.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/results.phtml index d6fdef6ae5f9a..dacf96f9c0baf 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/results.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/results.phtml @@ -32,7 +32,7 @@ $orderIds = $block->getOrderIds(); <?php $shippingAddress = $block->getOrderShippingAddress($orderId); ?> <div class="shipping-item"> <?php if ($shippingAddress) : ?> - <span class="shipping-label"><?= $block->escapeHtml('Ship to:'); ?></span> + <span class="shipping-label"><?= $block->escapeHtml(__('Ship to:')); ?></span> <span class="shipping-address"> <?= $block->escapeHtml($block->formatOrderShippingAddress($shippingAddress)); ?> </span> @@ -65,7 +65,7 @@ $orderIds = $block->getOrderIds(); <dl class="shipping-item"> <dt class="shipping-block"> <?php if ($block->isShippingAddress($address)) : ?> - <span class="shipping-label"><?= $block->escapeHtml('Ship to:'); ?></span> + <span class="shipping-label"><?= $block->escapeHtml(__('Ship to:')); ?></span> <span class="shipping-address"> <?= $block->escapeHtml($block->formatQuoteShippingAddress($address)); ?> </span> @@ -76,7 +76,7 @@ $orderIds = $block->getOrderIds(); <?php endif; ?> </dt> <dd class="error-block"> - <span class="error-label"><?= $block->escapeHtml('Error:'); ?></span> + <span class="error-label"><?= $block->escapeHtml(__('Error:')); ?></span> <span class="error-description"> <?= /* @noEscape */ $block->getAddressError($address); ?> </span> diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/success.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/success.phtml index c8e7c375089cd..57c4afaee6541 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/success.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/success.phtml @@ -22,7 +22,7 @@ <?php $shippingAddress = $block->getCheckoutData()->getOrderShippingAddress($orderId); ?> <div class="shipping-item"> <?php if ($shippingAddress) : ?> - <span class="shipping-label"><?= $block->escapeHtml('Ship to:'); ?></span> + <span class="shipping-label"><?= $block->escapeHtml(__('Ship to:')); ?></span> <span class="shipping-address"> <?= $block->escapeHtml( $block->getCheckoutData()->formatOrderShippingAddress($shippingAddress) diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml index cdd4779a2fd87..532fa88c4986a 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml @@ -135,7 +135,7 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); name="payment[is_active_payment_token_enabler]" class="admin__control-checkbox"/> <label class="admin__field-label" for="<?= /* @noEscape */ $code ?>_vault"> - <span><?= $block->escapeHtml('Save for later use.') ?></span> + <span><?= $block->escapeHtml(__('Save for later use.')) ?></span> </label> </div> <?php endif; ?> From 81289132743af3db8426d5e7d307c308811fa8d1 Mon Sep 17 00:00:00 2001 From: Nimesh Patel <patelnimesh1988@gmail.com> Date: Fri, 18 May 2018 13:25:11 +0530 Subject: [PATCH 0957/2023] Refactor javscript for customer logout --- .../view/frontend/templates/logout.phtml | 17 ++++++++--------- .../view/frontend/web/js/logout-redirect.js | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 app/code/Magento/Customer/view/frontend/web/js/logout-redirect.js diff --git a/app/code/Magento/Customer/view/frontend/templates/logout.phtml b/app/code/Magento/Customer/view/frontend/templates/logout.phtml index 43665045ce3e2..5a99b7d931b9b 100644 --- a/app/code/Magento/Customer/view/frontend/templates/logout.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/logout.phtml @@ -7,13 +7,12 @@ /** @var \Magento\Framework\View\Element\Template $block */ ?> <p><?= $block->escapeHtml(__('You have signed out and will go to our homepage in 5 seconds.')) ?></p> -<script> -require([ - "jquery", - "mage/mage" -], function($){ - - $($.mage.redirect("<?= $block->escapeJs($block->escapeUrl($block->getUrl())) ?>", "assign", 5000)); - -}); +<script type="text/x-magento-init"> + { + "*": { + "Magento_Customer/js/logout-redirect": { + "url": "<?= $block->escapeJs($block->escapeUrl($block->getUrl())) ?>" + } + } + } </script> diff --git a/app/code/Magento/Customer/view/frontend/web/js/logout-redirect.js b/app/code/Magento/Customer/view/frontend/web/js/logout-redirect.js new file mode 100644 index 0000000000000..c8d06e51fc39e --- /dev/null +++ b/app/code/Magento/Customer/view/frontend/web/js/logout-redirect.js @@ -0,0 +1,15 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + "jquery", + "mage/mage" +], function ($) { + 'use strict'; + + return function (data) { + $($.mage.redirect(data.url, "assign", 5000)); + }; +}); From 29223323076fae76c1c3f0b8d3de657088e60a5e Mon Sep 17 00:00:00 2001 From: Nimesh Patel <patelnimesh1988@gmail.com> Date: Fri, 18 May 2018 16:41:59 +0530 Subject: [PATCH 0958/2023] Fixed Invalid quote mark issue --- .../Customer/view/frontend/web/js/logout-redirect.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/view/frontend/web/js/logout-redirect.js b/app/code/Magento/Customer/view/frontend/web/js/logout-redirect.js index c8d06e51fc39e..6792626df6a08 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/logout-redirect.js +++ b/app/code/Magento/Customer/view/frontend/web/js/logout-redirect.js @@ -4,12 +4,12 @@ */ define([ - "jquery", - "mage/mage" + 'jquery', + 'mage/mage' ], function ($) { 'use strict'; return function (data) { - $($.mage.redirect(data.url, "assign", 5000)); + $($.mage.redirect(data.url, 'assign', 5000)); }; }); From 486f7a72c37ea04a5eeb1978bf2a8af0be9f0943 Mon Sep 17 00:00:00 2001 From: Alex Gusev <flancer64@gmail.com> Date: Tue, 15 May 2018 09:58:24 +0300 Subject: [PATCH 0959/2023] Error 500 in Module Manager There is an error in Module Manager (http://store.com/setup/index.php/moduleGrid/modules) if some module has no "moduleName" property: ``` { "name": "amzn\/amazon-pay-and-login-magento-2-module", "type": "magento2-module", "version": "2.0.4" } ``` --- setup/src/Magento/Setup/Model/Grid/Module.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Model/Grid/Module.php b/setup/src/Magento/Setup/Model/Grid/Module.php index c5e7c514df57c..c1b5dad5d9508 100644 --- a/setup/src/Magento/Setup/Model/Grid/Module.php +++ b/setup/src/Magento/Setup/Model/Grid/Module.php @@ -178,7 +178,7 @@ private function getModulesInfo(array $moduleList) private function addGeneralInfo(array $items) { foreach ($items as &$item) { - $item['moduleName'] = $item['moduleName'] ?: $this->packageInfo->getModuleName($item['name']); + $item['moduleName'] = isset($item['moduleName']) ? $item['moduleName'] : $this->packageInfo->getModuleName($item['name']); $item['enable'] = $this->moduleList->has($item['moduleName']); $vendorSource = $item['name'] == self::UNKNOWN_PACKAGE_NAME ? $item['moduleName'] : $item['name']; $item['vendor'] = ucfirst(current(preg_split('%[/_]%', $vendorSource))); From 1b5d1d1da3c9a4c01351f5c5ac34da9691c355a5 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@magento.com> Date: Mon, 21 May 2018 17:25:09 +0300 Subject: [PATCH 0960/2023] Fixed according to review --- setup/src/Magento/Setup/Model/Grid/Module.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/src/Magento/Setup/Model/Grid/Module.php b/setup/src/Magento/Setup/Model/Grid/Module.php index c1b5dad5d9508..fd9dc3285de3e 100644 --- a/setup/src/Magento/Setup/Model/Grid/Module.php +++ b/setup/src/Magento/Setup/Model/Grid/Module.php @@ -178,7 +178,7 @@ private function getModulesInfo(array $moduleList) private function addGeneralInfo(array $items) { foreach ($items as &$item) { - $item['moduleName'] = isset($item['moduleName']) ? $item['moduleName'] : $this->packageInfo->getModuleName($item['name']); + $item['moduleName'] = $item['moduleName'] ?? $this->packageInfo->getModuleName($item['name']); $item['enable'] = $this->moduleList->has($item['moduleName']); $vendorSource = $item['name'] == self::UNKNOWN_PACKAGE_NAME ? $item['moduleName'] : $item['name']; $item['vendor'] = ucfirst(current(preg_split('%[/_]%', $vendorSource))); From 037b97cb7a3062326121bc35947d5eeaae53d566 Mon Sep 17 00:00:00 2001 From: Jisse Reitsma <info@yireo.com> Date: Mon, 14 May 2018 11:25:13 +0200 Subject: [PATCH 0961/2023] Move buttons definition to separate file --- .../Magento/Ui/view/base/web/js/form/adapter.js | 10 +++------- .../Ui/view/base/web/js/form/adapter/buttons.js | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js diff --git a/app/code/Magento/Ui/view/base/web/js/form/adapter.js b/app/code/Magento/Ui/view/base/web/js/form/adapter.js index 0be9af06f9579..b623ce11603dd 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/adapter.js +++ b/app/code/Magento/Ui/view/base/web/js/form/adapter.js @@ -9,15 +9,11 @@ define([ 'jquery', 'underscore' -], function ($, _) { + './adapter/buttons' +], function ($, _, buttons) { 'use strict'; - var buttons = { - 'reset': '#reset', - 'save': '#save', - 'saveAndContinue': '#save_and_continue' - }, - selectorPrefix = '', + var selectorPrefix = '', eventPrefix; /** diff --git a/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js b/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js new file mode 100644 index 0000000000000..f1138608f3233 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js @@ -0,0 +1,15 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * @api + */ +define(function () { + return { + 'reset': '#reset', + 'save': '#save', + 'saveAndContinue': '#save_and_continue' + } +}); From fdb70a08ae43da8ad5601a9731886d7513690207 Mon Sep 17 00:00:00 2001 From: Jisse Reitsma <info@yireo.com> Date: Mon, 14 May 2018 16:05:13 +0200 Subject: [PATCH 0962/2023] Change relative path to absolute path for testability --- app/code/Magento/Ui/view/base/web/js/form/adapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/form/adapter.js b/app/code/Magento/Ui/view/base/web/js/form/adapter.js index b623ce11603dd..f864026259766 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/adapter.js +++ b/app/code/Magento/Ui/view/base/web/js/form/adapter.js @@ -9,7 +9,7 @@ define([ 'jquery', 'underscore' - './adapter/buttons' + 'Magento_Ui/js/form/adapter/buttons' ], function ($, _, buttons) { 'use strict'; From c70ba5b2967b705ed80dbc20b3f8a0670d20060e Mon Sep 17 00:00:00 2001 From: Jisse Reitsma <info@yireo.com> Date: Mon, 14 May 2018 16:05:47 +0200 Subject: [PATCH 0963/2023] Add strict mode --- app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js b/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js index f1138608f3233..fc43e6cdbb071 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js +++ b/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js @@ -7,6 +7,8 @@ * @api */ define(function () { + 'use strict'; + return { 'reset': '#reset', 'save': '#save', From a71b17808dc928e5a3c49c97052b29fa4efbdb2c Mon Sep 17 00:00:00 2001 From: Jisse Reitsma <info@yireo.com> Date: Mon, 14 May 2018 18:13:00 +0200 Subject: [PATCH 0964/2023] Fix missing comma --- app/code/Magento/Ui/view/base/web/js/form/adapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/form/adapter.js b/app/code/Magento/Ui/view/base/web/js/form/adapter.js index f864026259766..660d3382cb97c 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/adapter.js +++ b/app/code/Magento/Ui/view/base/web/js/form/adapter.js @@ -8,7 +8,7 @@ */ define([ 'jquery', - 'underscore' + 'underscore', 'Magento_Ui/js/form/adapter/buttons' ], function ($, _, buttons) { 'use strict'; From 526911c13a257357173ffc5bcfcc05dd2625e28b Mon Sep 17 00:00:00 2001 From: Jisse Reitsma <info@yireo.com> Date: Tue, 15 May 2018 07:30:29 +0200 Subject: [PATCH 0965/2023] Make sure colons are in right place --- app/code/Magento/Ui/view/base/web/js/form/adapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/form/adapter.js b/app/code/Magento/Ui/view/base/web/js/form/adapter.js index 660d3382cb97c..200aaa487107d 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/adapter.js +++ b/app/code/Magento/Ui/view/base/web/js/form/adapter.js @@ -13,8 +13,8 @@ define([ ], function ($, _, buttons) { 'use strict'; - var selectorPrefix = '', - eventPrefix; + var selectorPrefix = ''; + var eventPrefix; /** * Initialize listener. From 4b27bd81dca12b98f24155bb73cc10cbff2dafcb Mon Sep 17 00:00:00 2001 From: Jisse Reitsma <info@yireo.com> Date: Tue, 15 May 2018 16:06:52 +0200 Subject: [PATCH 0966/2023] Fix missing column because of eslint --- app/code/Magento/Ui/view/base/web/js/form/adapter.js | 4 ++-- app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/form/adapter.js b/app/code/Magento/Ui/view/base/web/js/form/adapter.js index 200aaa487107d..660d3382cb97c 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/adapter.js +++ b/app/code/Magento/Ui/view/base/web/js/form/adapter.js @@ -13,8 +13,8 @@ define([ ], function ($, _, buttons) { 'use strict'; - var selectorPrefix = ''; - var eventPrefix; + var selectorPrefix = '', + eventPrefix; /** * Initialize listener. diff --git a/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js b/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js index fc43e6cdbb071..2b939e25da479 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js +++ b/app/code/Magento/Ui/view/base/web/js/form/adapter/buttons.js @@ -13,5 +13,5 @@ define(function () { 'reset': '#reset', 'save': '#save', 'saveAndContinue': '#save_and_continue' - } + }; }); From 61856f5e6d5ed69c810183c95ad15b571f308a4d Mon Sep 17 00:00:00 2001 From: Elias Kotlyar <elias.kotlyar@gmail.com> Date: Tue, 29 May 2018 12:19:46 +0200 Subject: [PATCH 0967/2023] Fixxes #15565 --- app/code/Magento/Store/Model/PathConfig.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Store/Model/PathConfig.php b/app/code/Magento/Store/Model/PathConfig.php index dfe4eee31f9a2..83fa1f2072937 100644 --- a/app/code/Magento/Store/Model/PathConfig.php +++ b/app/code/Magento/Store/Model/PathConfig.php @@ -83,6 +83,8 @@ public function shouldBeSecure($path) */ public function getDefaultPath() { - return $this->scopeConfig->getValue('web/default/front', ScopeInterface::SCOPE_STORE); + $store = $this->storeManager->getStore(); + $value =$this->scopeConfig->getValue('web/default/front', ScopeInterface::SCOPE_STORE,$store); + return $value; } } From 4c77dff976361e70fc190c40b1fa5515cd136ce2 Mon Sep 17 00:00:00 2001 From: Vishal Gelani <vishalgelani99@gmail.com> Date: Tue, 29 May 2018 19:02:13 +0530 Subject: [PATCH 0968/2023] Fixed coding standard error --- app/code/Magento/Store/Model/PathConfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Store/Model/PathConfig.php b/app/code/Magento/Store/Model/PathConfig.php index 83fa1f2072937..6eeb93d7475fa 100644 --- a/app/code/Magento/Store/Model/PathConfig.php +++ b/app/code/Magento/Store/Model/PathConfig.php @@ -84,7 +84,7 @@ public function shouldBeSecure($path) public function getDefaultPath() { $store = $this->storeManager->getStore(); - $value =$this->scopeConfig->getValue('web/default/front', ScopeInterface::SCOPE_STORE,$store); + $value = $this->scopeConfig->getValue('web/default/front', ScopeInterface::SCOPE_STORE, $store); return $value; } } From 55d4cf8c4a601988bca0ee331b89f6f85a72f458 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 4 Jun 2018 13:42:13 +0300 Subject: [PATCH 0969/2023] MAGETWO-90808: [Performance] Customer Import check data does not complete --- app/code/Magento/CustomerImportExport/Model/Import/Address.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Address.php b/app/code/Magento/CustomerImportExport/Model/Import/Address.php index adff4afc79b4e..5ddf18031c7bc 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Address.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Address.php @@ -260,7 +260,6 @@ class Address extends AbstractCustomer * @param \Magento\Customer\Model\AddressFactory $addressFactory * @param \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionColFactory * @param \Magento\Customer\Model\CustomerFactory $customerFactory - * @param \Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressColFactory * @param \Magento\Customer\Model\ResourceModel\Address\Attribute\CollectionFactory $attributesFactory * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Customer\Model\Address\Validator\Postcode $postcodeValidator @@ -285,7 +284,6 @@ public function __construct( \Magento\Customer\Model\AddressFactory $addressFactory, \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionColFactory, \Magento\Customer\Model\CustomerFactory $customerFactory, - \Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressColFactory, \Magento\Customer\Model\ResourceModel\Address\Attribute\CollectionFactory $attributesFactory, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Customer\Model\Address\Validator\Postcode $postcodeValidator, From bcdd8f2a6fdc722828b3c0d3ac72fd19df1ae226 Mon Sep 17 00:00:00 2001 From: Saurabh Parekh <saurabh.parekh@aureatelabs.com> Date: Sat, 19 May 2018 13:35:23 +0530 Subject: [PATCH 0970/2023] Function unnecessarily called multiple time --- .../Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml index 7dca29263bae3..0ba3c7ed2d7d6 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml @@ -13,8 +13,6 @@ */ ?> -<?php $block->getCurrencySymbolsData();?> - <form id="currency-symbols-form" action="<?= /* @escapeNotVerified */ $block->getFormActionUrl() ?>" method="post"> <input name="form_key" type="hidden" value="<?= /* @escapeNotVerified */ $block->getFormKey() ?>" /> <fieldset class="admin__fieldset"> From ecc5f7b4ae8c43f588710bb6bc7c6183ccaf2538 Mon Sep 17 00:00:00 2001 From: hitesh-wagento <hitesh@wagento.com> Date: Mon, 4 Jun 2018 16:25:36 +0530 Subject: [PATCH 0971/2023] [Forwardport] [Resolved : Menu widget submenu alignment] --- lib/web/css/source/lib/_navigation.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/web/css/source/lib/_navigation.less b/lib/web/css/source/lib/_navigation.less index 6ed3a9671ab13..56aa2e7ef86b9 100644 --- a/lib/web/css/source/lib/_navigation.less +++ b/lib/web/css/source/lib/_navigation.less @@ -305,6 +305,10 @@ .lib-css(border-top, none); } + li.level1 { + position: relative; + } + .level0 { .lib-css(margin, @_nav-level0-item-margin); display: inline-block; From d58ab5fc8d290e162daadf4006b958b0f1de972f Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta <riccardo.tempesta@magespecialist.it> Date: Sat, 26 May 2018 15:56:23 +0200 Subject: [PATCH 0972/2023] FIX fo rissue #15510 - First PDF download / export after login --- app/code/Magento/Backend/App/AbstractAction.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/code/Magento/Backend/App/AbstractAction.php b/app/code/Magento/Backend/App/AbstractAction.php index 99ee86b2b6407..3f658ee90bf4e 100644 --- a/app/code/Magento/Backend/App/AbstractAction.php +++ b/app/code/Magento/Backend/App/AbstractAction.php @@ -217,6 +217,7 @@ public function dispatch(\Magento\Framework\App\RequestInterface $request) $this->_view->loadLayout(['default', 'adminhtml_denied'], true, true, false); $this->_view->renderLayout(); $this->_request->setDispatched(true); + return $this->_response; } @@ -226,6 +227,11 @@ public function dispatch(\Magento\Framework\App\RequestInterface $request) $this->_processLocaleSettings(); + // Need to preload isFirstPageAfterLogin (see https://github.com/magento/magento2/issues/15510) + if ($this->_auth->isLoggedIn()) { + $this->_auth->getAuthStorage()->isFirstPageAfterLogin(); + } + return parent::dispatch($request); } From e13f1f0771998031adbc1e4c3d03f36dfb5984d5 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta <riccardo.tempesta@magespecialist.it> Date: Sat, 26 May 2018 15:05:06 +0200 Subject: [PATCH 0973/2023] FIX for issue #15457 - Bundle Products price range is showing expired special price from bundle options --- .../Pricing/Adjustment/DefaultSelectionPriceListProvider.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/DefaultSelectionPriceListProvider.php b/app/code/Magento/Bundle/Pricing/Adjustment/DefaultSelectionPriceListProvider.php index 56c403ad9960c..297c4659cb877 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/DefaultSelectionPriceListProvider.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/DefaultSelectionPriceListProvider.php @@ -61,8 +61,8 @@ public function getPriceList(Product $bundleProduct, $searchMin, $useRegularPric if (!$useRegularPrice) { $selectionsCollection->addAttributeToSelect('special_price'); - $selectionsCollection->addAttributeToSelect('special_price_from'); - $selectionsCollection->addAttributeToSelect('special_price_to'); + $selectionsCollection->addAttributeToSelect('special_from_date'); + $selectionsCollection->addAttributeToSelect('special_to_date'); $selectionsCollection->addAttributeToSelect('tax_class_id'); } From c9435610db0d4e9a71d93e5fb467cb6bef3e9336 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Mon, 4 Jun 2018 14:34:19 +0300 Subject: [PATCH 0974/2023] MAGETWO-50831: Impossible specify Bundle option title on store view level --- .../Bundle/Model/Product/SaveHandler.php | 14 ++++++-------- .../Bundle/Model/Product/SaveHandlerTest.php | 5 ++++- .../Model/Export/RowCustomizerTest.php | 17 +++++++++++++---- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Bundle/Model/Product/SaveHandler.php b/app/code/Magento/Bundle/Model/Product/SaveHandler.php index 6a860bab4fb7b..fc215aa6b8e20 100644 --- a/app/code/Magento/Bundle/Model/Product/SaveHandler.php +++ b/app/code/Magento/Bundle/Model/Product/SaveHandler.php @@ -139,14 +139,12 @@ private function getOptionIds(array $options): array { $optionIds = []; - if (empty($options)) { - return $optionIds; - } - - /** @var \Magento\Bundle\Api\Data\OptionInterface $option */ - foreach ($options as $option) { - if ($option->getOptionId()) { - $optionIds[] = $option->getOptionId(); + if (!empty($options)) { + /** @var \Magento\Bundle\Api\Data\OptionInterface $option */ + foreach ($options as $option) { + if ($option->getOptionId()) { + $optionIds[] = $option->getOptionId(); + } } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/SaveHandlerTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/SaveHandlerTest.php index 46bfbea3eebd7..381675d01ae1d 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/SaveHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/SaveHandlerTest.php @@ -46,7 +46,10 @@ protected function setUp() $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); } - public function testOptionTitlesOnDifferentStores() + /** + * @return void + */ + public function testOptionTitlesOnDifferentStores(): void { /** * @var \Magento\Bundle\Model\Product\OptionList $optionList diff --git a/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php b/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php index 6a7d0f2e51c20..53e8281ffbdf1 100644 --- a/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php +++ b/dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php @@ -20,6 +20,9 @@ class RowCustomizerTest extends \PHPUnit\Framework\TestCase */ private $objectManager; + /** + * @inheritdoc + */ protected function setUp() { $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); @@ -30,8 +33,10 @@ protected function setUp() /** * @magentoDataFixture Magento/Bundle/_files/product.php + * + * @return void */ - public function testPrepareData() + public function testPrepareData(): void { $parsedAdditionalAttributes = 'text_attribute=!@#$%^&*()_+1234567890-=|\\:;"\'<,>.?/' . ',text_attribute2=,'; @@ -61,13 +66,15 @@ public function testPrepareData() * @magentoDataFixture Magento/Store/_files/second_store.php * @magentoDataFixture Magento/Bundle/_files/product.php * @magentoDbIsolation disabled + * + * @return void */ - public function testPrepareDataWithDifferentStoreValues() + public function testPrepareDataWithDifferentStoreValues(): void { $storeCode = 'default'; $expectedNames = [ 'name' => 'Bundle Product Items', - 'name_' . $storeCode => 'Bundle Product Items_' . $storeCode + 'name_' . $storeCode => 'Bundle Product Items_' . $storeCode, ]; $parsedAdditionalAttributes = 'text_attribute=!@#$%^&*()_+1234567890-=|\\:;"\'<,>.?/' . ',text_attribute2=,'; @@ -94,14 +101,16 @@ public function testPrepareDataWithDifferentStoreValues() $bundleValues = array_map( function ($input) { $data = explode('=', $input); + return [$data[0] => $data[1]]; }, explode(',', $result['bundle_values']) ); $actualNames = [ 'name' => array_column($bundleValues, 'name')[0], - 'name' . '_' . $store->getCode() => array_column($bundleValues, 'name' . '_' . $store->getCode())[0] + 'name' . '_' . $store->getCode() => array_column($bundleValues, 'name' . '_' . $store->getCode())[0], ]; + self::assertSame($expectedNames, $actualNames); } } From d1ed33c6a3e674f8ea6adf97c47d29a0ea480cf2 Mon Sep 17 00:00:00 2001 From: Stas Kozar <stas.kozar@transoftgroup.com> Date: Mon, 4 Jun 2018 14:38:41 +0300 Subject: [PATCH 0975/2023] MAGETWO-90739: Out of stock options for configurable products still show up in search and layered navigation if Elasticsearch is enabled --- .../Model/Indexer/Plugin/DependencyUpdaterPluginTest.php | 3 +++ .../Model/Indexer/Plugin/StockedProductsFilterPluginTest.php | 3 +++ .../Magento/Elasticsearch/_files/configurable_attribute.php | 1 - .../Elasticsearch/_files/configurable_attribute_rollback.php | 5 ----- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/DependencyUpdaterPluginTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/DependencyUpdaterPluginTest.php index 9b43d7d40ab1a..15510843b0e60 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/DependencyUpdaterPluginTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/DependencyUpdaterPluginTest.php @@ -33,6 +33,9 @@ class DependencyUpdaterPluginTest extends \PHPUnit\Framework\TestCase */ private $providerMock; + /** + * {@inheritdoc} + */ protected function setUp() { $this->configMock = $this->getMockBuilder(Config::class) diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php index dc4a92016d1fb..f66d2532b32ae 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/Model/Indexer/Plugin/StockedProductsFilterPluginTest.php @@ -48,6 +48,9 @@ class StockedProductsFilterPluginTest extends \PHPUnit\Framework\TestCase */ private $plugin; + /** + * {@inheritdoc} + */ protected function setUp() { $this->configMock = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock(); diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute.php index 66d4d467bf6f4..7ec53d9099d35 100644 --- a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute.php +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute.php @@ -17,7 +17,6 @@ $installer = Bootstrap::getObjectManager()->create(\Magento\Catalog\Setup\CategorySetup::class); if (!$attribute->getId()) { - /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ $attribute = Bootstrap::getObjectManager()->create( \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class diff --git a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute_rollback.php index f302df996f902..7bdfbc6d7f9b3 100644 --- a/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Elasticsearch/_files/configurable_attribute_rollback.php @@ -10,11 +10,6 @@ $registry->unregister('isSecureArea'); $registry->register('isSecureArea', true); -$productCollection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->get(\Magento\Catalog\Model\ResourceModel\Product\Collection::class); -foreach ($productCollection as $product) { - $product->delete(); -} $eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Eav\Model\Config::class); $attribute = $eavConfig->getAttribute('catalog_product', 'test_configurable'); From 38cabd3b517a5cfec6ce1ed01071da38b2a538ea Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 4 Jun 2018 15:08:16 +0300 Subject: [PATCH 0976/2023] MAGETWO-90808: [Performance] Customer Import check data does not complete --- .../CustomerImportExport/Test/Unit/Model/Import/AddressTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php index 113d6fa06ba31..126a9e1791779 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php @@ -445,7 +445,6 @@ protected function _getModelMock() $this->createMock(\Magento\Customer\Model\AddressFactory::class), $this->createMock(\Magento\Directory\Model\ResourceModel\Region\CollectionFactory::class), $this->createMock(\Magento\Customer\Model\CustomerFactory::class), - $this->createMock(\Magento\Customer\Model\ResourceModel\Address\CollectionFactory::class), $this->createMock(\Magento\Customer\Model\ResourceModel\Address\Attribute\CollectionFactory::class), new \Magento\Framework\Stdlib\DateTime(), $this->createMock(\Magento\Customer\Model\Address\Validator\Postcode::class), From c2765a77db48e5d2819500c68b51947ebd7e8bf0 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets <vzaets@magento.com> Date: Mon, 4 Jun 2018 16:33:02 +0300 Subject: [PATCH 0977/2023] Update AbstractMultishipping.php Fix typo in doc block. --- .../Multishipping/Block/Checkout/AbstractMultishipping.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php b/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php index 0de66ccd505a4..d3c17a8d7c8de 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php +++ b/app/code/Magento/Multishipping/Block/Checkout/AbstractMultishipping.php @@ -5,7 +5,7 @@ */ /** - * Mustishipping checkout base abstract block + * Multishipping checkout base abstract block * * @author Magento Core Team <core@magentocommerce.com> */ From ac51a3ca2d6f902cb29e69c342d4fb7c05659de6 Mon Sep 17 00:00:00 2001 From: Roman Ganin <rganin@magento.com> Date: Mon, 4 Jun 2018 10:09:47 -0500 Subject: [PATCH 0978/2023] MAGETWO-91570: [2.2.x] - [Github]Can not save attribute #5907 --- .../Adminhtml/Product/Attribute/Save.php | 23 +++++++++++++++ .../Catalog/view/adminhtml/web/js/options.js | 28 ++++++++++++++++--- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index 6a9abe0a4c64e..31c98af39c040 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -69,6 +69,7 @@ class Save extends Attribute * @var LayoutFactory */ private $layoutFactory; + /** * @var Presentation */ @@ -124,6 +125,7 @@ public function execute() { $data = $this->getRequest()->getPostValue(); if ($data) { + $this->extractOptionsData($data); $setId = $this->getRequest()->getParam('set'); $attributeSet = null; @@ -315,6 +317,27 @@ public function execute() return $this->returnResult('catalog/*/', [], ['error' => true]); } + /** + * Extract options data from serialized options field. + * This logic is required to overcome max_input_vars php limit + * that may vary and/or be inaccessible to change on different instances. + * + * @param array $data + * @return void + */ + private function extractOptionsData(&$data) + { + if (isset($data['serialized_options'])) { + unset($data['option']); + $serializedOptions = json_decode($data['serialized_options'], JSON_OBJECT_AS_ARRAY); + foreach ($serializedOptions as $serializedOption) { + $option = []; + parse_str($serializedOption, $option); + $data = array_replace_recursive($data, $option); + } + } + } + /** * @param string $path * @param array $params diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js index 787516a9abf29..ce9dc4870b941 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js @@ -13,12 +13,16 @@ define([ 'jquery/ui', 'prototype', 'form', - 'validation' + 'validation', + 'mage/translate' ], function (jQuery, mageTemplate, rg) { 'use strict'; return function (config) { - var attributeOption = { + var optionPanel = jQuery('#manage-options-panel'), + optionsValues = [], + editForm = jQuery('#edit_form'), + attributeOption = { table: $('attribute-options-table'), itemCount: 0, totalItems: 0, @@ -150,7 +154,7 @@ define([ attributeOption.remove(event); }); - jQuery('#manage-options-panel').on('render', function () { + optionPanel.on('render', function () { attributeOption.ignoreValidate(); if (attributeOption.rendered) { @@ -176,7 +180,23 @@ define([ }); }); } - + editForm.on('submit', function () { + editForm + .find('input[name^="option"]') + .each(function() { + optionsValues.push(this.name + '=' + jQuery(this).val()); + this.closest('tr').hide() + }); + jQuery('<input>') + .attr({ + type: 'hidden', + name: 'serialized_options' + }) + .val(JSON.stringify(optionsValues)) + .prependTo('#edit_form'); + optionPanel.find('table') + .replaceWith(jQuery('<div>').text(jQuery.mage.__('Sending attribute values as package.'))); + }); window.attributeOption = attributeOption; window.optionDefaultInputType = attributeOption.getOptionInputType(); From 64c975aa8efe32c0f4b7bb9d4510ca261404116b Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@magento.com> Date: Mon, 4 Jun 2018 10:12:08 -0500 Subject: [PATCH 0979/2023] MC-239: Customer should only see cart price rule discount if condition shipping state/province - Fill in missing title, description. - Remove "banana" testing group --- .../SalesRule/Test/StorefrontCartPriceRuleState.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleState.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleState.xml index a5c4a18591f31..13238b507393a 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleState.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleState.xml @@ -12,12 +12,11 @@ <annotations> <features value="SalesRule"/> <stories value="Create cart price rule"/> - <title value=""/> - <description value=""/> + <title value="Customer should only see cart price rule discount if condition shipping state/province"/> + <description value="Customer should only see cart price rule discount if condition shipping state/province"/> <severity value="AVERAGE"/> <testCaseId value="MC-239"/> <group value="SalesRule"/> - <group value="banana"/> </annotations> <before> From 402d5655e14e5ee73a36f54cb282acd267b7f43e Mon Sep 17 00:00:00 2001 From: Roman Ganin <rganin@magento.com> Date: Mon, 21 May 2018 13:11:50 -0500 Subject: [PATCH 0980/2023] MAGETWO-91958: EE install fails on 7.2.5 with fatal error --- .../Setup/Declaration/Schema/Db/DDLTriggerInterface.php | 2 +- .../Schema/Db/MySQL/DDL/Triggers/MigrateDataBetweenShards.php | 2 +- .../Schema/Db/MySQL/DDL/Triggers/MigrateDataFrom.php | 2 +- .../Db/MySQL/DDL/Triggers/MigrateDataFromAnotherTable.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/DDLTriggerInterface.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/DDLTriggerInterface.php index 8d5e03000316f..596e66367c727 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/DDLTriggerInterface.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/DDLTriggerInterface.php @@ -42,5 +42,5 @@ public function isApplicable(string $statement) : bool ; * @param ElementHistory $elementHistory * @return callable */ - public function getCallback(ElementHistory $elementHistory) : Callable; + public function getCallback(ElementHistory $elementHistory) : callable; } diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataBetweenShards.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataBetweenShards.php index ad69ff92c8a5a..4c1b2b8373c52 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataBetweenShards.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataBetweenShards.php @@ -62,7 +62,7 @@ public function isApplicable(string $statement) : bool /** * @inheritdoc */ - public function getCallback(ElementHistory $elementHistory) : Callable + public function getCallback(ElementHistory $elementHistory) : callable { /** @var Table $newTable */ $newTable = $elementHistory->getNew(); diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFrom.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFrom.php index 5ad5c2cd6a209..cb969fb9367f2 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFrom.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFrom.php @@ -50,7 +50,7 @@ public function isApplicable(string $statement) : bool /** * @inheritdoc */ - public function getCallback(ElementHistory $columnHistory) : Callable + public function getCallback(ElementHistory $columnHistory) : callable { /** @var Column $column */ $column = $columnHistory->getNew(); diff --git a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFromAnotherTable.php b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFromAnotherTable.php index 6c426723ab370..0f97fc9d6f243 100644 --- a/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFromAnotherTable.php +++ b/lib/internal/Magento/Framework/Setup/Declaration/Schema/Db/MySQL/DDL/Triggers/MigrateDataFromAnotherTable.php @@ -49,7 +49,7 @@ public function isApplicable(string $statement) : bool /** * @inheritdoc */ - public function getCallback(ElementHistory $tableHistory) : Callable + public function getCallback(ElementHistory $tableHistory) : callable { /** @var Table $table */ $table = $tableHistory->getNew(); From 3c9066cf0bbc7ba1c90e4d2e72e350d45fcf4bbf Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@magento.com> Date: Mon, 4 Jun 2018 10:39:20 -0500 Subject: [PATCH 0981/2023] MC-241: Customer should only see cart price rule discount if condition shipping country --- .../Section/CheckoutCartSummarySection.xml | 1 + .../Test/StorefrontCartPriceRuleCountry.xml | 88 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleCountry.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml index 27d23143aff9d..248070940542c 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Checkout/Section/CheckoutCartSummarySection.xml @@ -18,5 +18,6 @@ <element name="shippingHeading" type="button" selector="#block-shipping-heading"/> <element name="postcode" type="input" selector="input[name='postcode']"/> <element name="stateProvince" type="select" selector="select[name='region_id']"/> + <element name="country" type="select" selector="select[name='country_id']"/> </section> </sections> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleCountry.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleCountry.xml new file mode 100644 index 0000000000000..0f7bf3d9eaf33 --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/SalesRule/Test/StorefrontCartPriceRuleCountry.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="StorefrontCartPriceRuleCountry"> + <annotations> + <features value="SalesRule"/> + <stories value="Create cart price rule"/> + <title value="Customer should only see cart price rule discount if condition shipping country"/> + <description value="Customer should only see cart price rule discount if condition shipping country"/> + <severity value="AVERAGE"/> + <testCaseId value="MC-241"/> + <group value="SalesRule"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + <createData entity="_defaultProduct" stepKey="createPreReqProduct"> + <requiredEntity createDataKey="createPreReqCategory"/> + </createData> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + + <after> + <actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule"> + <argument name="ruleName" value="{{SimpleSalesRule.name}}"/> + </actionGroup> + <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + <deleteData createDataKey="createPreReqProduct" stepKey="deletePreReqProduct"/> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + </after> + + <!-- Create the rule... --> + <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> + <waitForPageLoad stepKey="waitForRulesPage"/> + <click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule"/> + <fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{SimpleSalesRule.name}}" stepKey="fillRuleName"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="Main Website" stepKey="selectWebsites"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" userInput="NOT LOGGED IN" stepKey="selectCustomerGroup"/> + <click selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="expandConditions"/> + <!-- Scroll down to fix some flaky behavior... --> + <scrollTo selector="{{PriceRuleConditionsSection.conditionsTab}}" stepKey="scrollToConditionsTab"/> + <waitForElementVisible selector="{{PriceRuleConditionsSection.createNewRule}}" stepKey="waitForNewRule"/> + <click selector="{{PriceRuleConditionsSection.createNewRule}}" stepKey="clickNewRule"/> + <selectOption selector="{{PriceRuleConditionsSection.rulesDropdown}}" userInput="Shipping Country" stepKey="selectProductAttributes"/> + <waitForPageLoad stepKey="wait1"/> + <click selector="{{PriceRuleConditionsSection.ruleParamLink('1', '1', '2')}}" stepKey="startEditValue"/> + <waitForPageLoad stepKey="wait4"/> + <selectOption selector="{{PriceRuleConditionsSection.valueByIndex('1', '1')}}" userInput="Brazil" stepKey="fillValue"/> + <waitForPageLoad stepKey="wait5"/> + <click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions"/> + <selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="Fixed amount discount for whole cart" stepKey="selectActionType"/> + <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="9.99" stepKey="fillDiscountAmount"/> + <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> + <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> + + <!-- Add the product we created to our cart --> + <amOnPage url="$$createPreReqProduct.name$$.html" stepKey="goToProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <fillField selector="{{StorefrontProductActionSection.quantity}}" userInput="1" stepKey="fillQuantity"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart"/> + <waitForPageLoad stepKey="waitForAddToCart"/> + + <!-- Should not see the discount yet because we have not set country --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCartPage"/> + <waitForPageLoad stepKey="waitForCartPage"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$123.00" stepKey="seeSubtotal"/> + <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount"/> + + <!-- See discount if we use valid country --> + <click selector="{{CheckoutCartSummarySection.shippingHeading}}" stepKey="expandShipping"/> + <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="Brazil" stepKey="fillCountry"/> + <waitForPageLoad stepKey="waitForCountry1"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$9.99" stepKey="seeDiscountTotal"/> + + <!-- Do not see discount with other country --> + <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="United States" stepKey="fillCountry2"/> + <waitForPageLoad stepKey="waitForCountry2"/> + <dontSeeElement selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="dontSeeDiscount2"/> + </test> +</tests> From d713007c24eaaccbc86104bfc8345823ae8f7d94 Mon Sep 17 00:00:00 2001 From: Torrey Tsui <tt@amp.co> Date: Mon, 15 Jan 2018 16:44:28 +0000 Subject: [PATCH 0982/2023] Clear shipping tax residue on emptying basket --- app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php index de884be6bc839..4aea7ab4c5a7c 100755 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php @@ -152,12 +152,23 @@ protected function clearValues(Address\Total $total) $total->setBaseTotalAmount('subtotal', 0); $total->setTotalAmount('tax', 0); $total->setBaseTotalAmount('tax', 0); + $total->setTotalAmount('shipping', 0); + $total->setBaseTotalAmount('shipping', 0); $total->setTotalAmount('discount_tax_compensation', 0); $total->setBaseTotalAmount('discount_tax_compensation', 0); $total->setTotalAmount('shipping_discount_tax_compensation', 0); $total->setBaseTotalAmount('shipping_discount_tax_compensation', 0); $total->setSubtotalInclTax(0); $total->setBaseSubtotalInclTax(0); + $total->setShippingInclTax(0); + $total->setBaseShippingInclTax(0); + $total->setShippingTaxAmount(0); + $total->setBaseShippingTaxAmount(0); + $total->setShippingAmountForDiscount(0); + $total->setBaseShippingAmountForDiscount(0); + $total->setBaseShippingAmountForDiscount(0); + $total->setTotalAmount('extra_tax', 0); + $total->setBaseTotalAmount('extra_tax', 0); } /** From c5ca935fa566560326b4b71e4e6c8457a6f96d7d Mon Sep 17 00:00:00 2001 From: Alex Paliarush <apaliarush@magento.com> Date: Mon, 4 Jun 2018 14:27:04 -0500 Subject: [PATCH 0983/2023] ENGCOM-1833: Limit list of filterable product fields #26 --- app/code/Magento/CatalogGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/TaxGraphQl/etc/schema.graphqls | 8 -------- .../testsuite/Magento/GraphQl/Catalog/CategoryTest.php | 2 -- .../testsuite/Magento/GraphQl/Catalog/ProductViewTest.php | 3 --- .../Magento/GraphQl/Catalog/VirtualProductViewTest.php | 3 --- 5 files changed, 1 insertion(+), 17 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 04002e08795a0..f9df24e8ff731 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -441,6 +441,7 @@ input ProductFilterInput @doc(description: "ProductFilterInput defines the filte min_price: FilterTypeInput @doc(description:"The numeric minimal price of the product. Do not include the currency code.") max_price: FilterTypeInput @doc(description:"The numeric maximal price of the product. Do not include the currency code.") special_price: FilterTypeInput @doc(description:"The numeric special price of the product. Do not include the currency code.") + category_ids: FilterTypeInput @doc(description: "An array of category IDs the product belongs to") options_container: FilterTypeInput @doc(description: "If the product has multiple options, determines where they appear on the product page") required_options: FilterTypeInput @doc(description: "Indicates whether the product has required options") has_options: FilterTypeInput @doc(description: "Indicates whether additional attributes have been created for the product") @@ -491,7 +492,6 @@ input ProductSortInput @doc(description: "ProductSortInput specifies the attrib news_from_date: SortEnum @doc(description: "The beginning date for new product listings, and determines if the product is featured as a new product") news_to_date: SortEnum @doc(description: "The end date for new product listings") custom_layout_update: SortEnum @doc(description: "XML code that is applied as a layout update to the product page") - category_ids: SortEnum @doc(description: "An array of category IDs the product belongs to") options_container: SortEnum @doc(description: "If the product has multiple options, determines where they appear on the product page") required_options: SortEnum @doc(description: "Indicates whether the product has required options") has_options: SortEnum @doc(description: "Indicates whether additional attributes have been created for the product") diff --git a/app/code/Magento/TaxGraphQl/etc/schema.graphqls b/app/code/Magento/TaxGraphQl/etc/schema.graphqls index eafb390983973..2b81983478447 100644 --- a/app/code/Magento/TaxGraphQl/etc/schema.graphqls +++ b/app/code/Magento/TaxGraphQl/etc/schema.graphqls @@ -1,14 +1,6 @@ # Copyright © Magento, Inc. All rights reserved. # See COPYING.txt for license details. -interface ProductInterface { - tax_class_id: Int -} - -input ProductSortInput { - tax_class_id: SortEnum -} - enum PriceAdjustmentCodesEnum { TAX } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php index 223fa75006d45..dca3bf9abd182 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php @@ -232,7 +232,6 @@ public function testCategoryProducts() special_price special_to_date swatch_image - tax_class_id thumbnail thumbnail_label tier_price @@ -358,7 +357,6 @@ private function assertAttributes($actualResponse) 'meta_keyword', 'meta_title', 'short_description', - 'tax_class_id', 'country_of_manufacture', 'gift_message_available', 'new_from_date', diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php index aaf22c8b373fe..b5aa73a5a7a34 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductViewTest.php @@ -211,7 +211,6 @@ public function testQueryAllFieldsSimpleProduct() special_price special_to_date swatch_image - tax_class_id thumbnail thumbnail_label tier_price @@ -460,7 +459,6 @@ public function testQueryMediaGalleryEntryFieldsSimpleProduct() special_price special_to_date swatch_image - tax_class_id thumbnail thumbnail_label tier_price @@ -922,7 +920,6 @@ private function assertEavAttributes($product, $actualResponse) 'meta_keyword', 'meta_title', 'short_description', - 'tax_class_id', 'country_of_manufacture', 'gift_message_available', 'news_from_date', diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/VirtualProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/VirtualProductViewTest.php index f38d71c9b4039..df3386f2f7836 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/VirtualProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/VirtualProductViewTest.php @@ -36,7 +36,6 @@ public function testQueryAllFieldsVirtualProduct() name sku type_id - tax_class_id updated_at ... on PhysicalProductInterface { weight @@ -96,7 +95,6 @@ public function testCannotQueryWeightOnVirtualProductException() name sku type_id - tax_class_id updated_at ... on PhysicalProductInterface { weight @@ -130,7 +128,6 @@ private function assertBaseFields($product, $actualResponse) ['response_field' => 'attribute_set_id', 'expected_value' => $product->getAttributeSetId()], ['response_field' => 'id', 'expected_value' => $product->getId()], ['response_field' => 'name', 'expected_value' => $product->getName()], - ['response_field' => 'tax_class_id', 'expected_value' => $product->getTaxClassId()], ['response_field' => 'sku', 'expected_value' => $product->getSku()], ['response_field' => 'type_id', 'expected_value' => $product->getTypeId()] ]; From dc1400ebfdc1e4245a228ea2b11a2969cbbfd186 Mon Sep 17 00:00:00 2001 From: Roman Ganin <rganin@magento.com> Date: Mon, 4 Jun 2018 15:09:10 -0500 Subject: [PATCH 0984/2023] MAGETWO-91570: [2.2.x] - [Github]Can not save attribute #5907 --- .../Adminhtml/Product/AttributeTest.php | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php index fdc85941b32e9..00ee7afeba1e0 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ namespace Magento\Catalog\Controller\Adminhtml\Product; +use Magento\Framework\Exception\LocalizedException; /** * @magentoAppArea adminhtml @@ -224,6 +225,104 @@ public function testSaveActionCleanAttributeLabelCache() $this->assertEquals('new string translation', $this->_translate('string to translate')); } + /** + * Get attribute data preset. + * + * @return array + */ + private function getLargeOptionsSetAttributeData() + { + return [ + 'frontend_label' => [ + 0 => 'testdrop1', + 1 => '', + 2 => '', + ], + 'frontend_input' => 'select', + 'is_required' => '0', + 'update_product_preview_image' => '0', + 'use_product_image_for_swatch' => '0', + 'visual_swatch_validation' => '', + 'visual_swatch_validation_unique' => '', + 'text_swatch_validation' => '', + 'text_swatch_validation_unique' => '', + 'attribute_code' => 'test_many_options', + 'is_global' => '0', + 'default_value_text' => '', + 'default_value_yesno' => '0', + 'default_value_date' => '', + 'default_value_textarea' => '', + 'is_unique' => '0', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '0', + 'is_comparable' => '0', + 'is_filterable' => '0', + 'is_filterable_in_search' => '0', + 'is_used_for_promo_rules' => '0', + 'is_html_allowed_on_front' => '1', + 'is_visible_on_front' => '0', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '0', + 'swatch_input_type' => 'dropdown', + ]; + } + + /** + * Test attribute saving with large amount of options exceeding maximum allowed by max_input_vars limit. + * @return void + */ + public function testLargeOptionsDataSet() + { + $maxInputVars = ini_get('max_input_vars'); + // Each option is at least 4 variables array (order, admin value, first store view value, delete flag). + // Set options count to exceed max_input_vars by 100 options (400 variables). + $optionsCount = floor($maxInputVars / 4) + 100; + $attributeData = $this->getLargeOptionsSetAttributeData(); + $optionsData = []; + $expectedOptionsLabels = []; + for ($i = 0; $i < $optionsCount; $i++) { + $order = $i + 1; + $expectedOptionLabelOnStoreView = "value_{$i}_store_1"; + $expectedOptionsLabels[$i+1] = $expectedOptionLabelOnStoreView; + $optionsData []= "option[order][option_{$i}]={$order}"; + $optionsData []= "option[value][option_{$i}][0]=value_{$i}_admin"; + $optionsData []= "option[value][option_{$i}][1]={$expectedOptionLabelOnStoreView}"; + $optionsData []= "option[delete][option_{$i}="; + } + $attributeData['serialized_options'] = json_encode($optionsData); + $this->getRequest()->setPostValue($attributeData); + $this->dispatch('backend/catalog/product_attribute/save'); + $entityTypeId = $this->_objectManager->create( + \Magento\Eav\Model\Entity::class + )->setType( + \Magento\Catalog\Model\Product::ENTITY + )->getTypeId(); + + /** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ + $attribute = $this->_objectManager->create( + \Magento\Catalog\Model\ResourceModel\Eav\Attribute::class + )->setEntityTypeId( + $entityTypeId + ); + try { + $attribute->loadByCode($entityTypeId, 'test_many_options'); + $options = $attribute->getOptions(); + // assert that all options are saved without truncation + $this->assertEquals( + $optionsCount + 1, + count($options), + 'Expected options count does not match (regarding first empty option for non-required attribute)' + ); + + foreach ($expectedOptionsLabels as $optionOrderNum => $label) { + $this->assertEquals($label, $options[$optionOrderNum]->getLabel(), 'Label does not match expected.'); + } + } catch (LocalizedException $e) { + $this->fail('Test failed with exception on attribute model load: ' . $e); + } + } /** * Return translation for a string literal belonging to backend area * From 18cb5bdbd441cb4df1c9351ad394682eed939f88 Mon Sep 17 00:00:00 2001 From: Roman Ganin <rganin@magento.com> Date: Mon, 4 Jun 2018 15:22:59 -0500 Subject: [PATCH 0985/2023] MAGETWO-91570: [2.2.x] - [Github]Can not save attribute #5907 --- .../Catalog/Controller/Adminhtml/Product/AttributeTest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php index 00ee7afeba1e0..c037e48758c85 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php @@ -317,12 +317,17 @@ public function testLargeOptionsDataSet() ); foreach ($expectedOptionsLabels as $optionOrderNum => $label) { - $this->assertEquals($label, $options[$optionOrderNum]->getLabel(), 'Label does not match expected.'); + $this->assertEquals( + $label, + $options[$optionOrderNum]->getLabel(), + "Label for option #{$optionOrderNum} does not match expected." + ); } } catch (LocalizedException $e) { $this->fail('Test failed with exception on attribute model load: ' . $e); } } + /** * Return translation for a string literal belonging to backend area * From eaf8caab717b7fd77974446a22c6f26058a1551b Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@magento.com> Date: Mon, 4 Jun 2018 16:29:21 -0500 Subject: [PATCH 0986/2023] MAGETWO-91434: Default option for Status attribute not being set - added functional test to cover bug fix --- .../Section/AdminProductFormSection.xml | 1 + ...ctStatusAttributeDisabledByDefaultTest.xml | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminProductStatusAttributeDisabledByDefaultTest.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductFormSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductFormSection.xml index 926d87e889931..e329ae5e639ab 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductFormSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Section/AdminProductFormSection.xml @@ -10,6 +10,7 @@ <section name="AdminProductFormSection"> <element name="productName" type="input" selector=".admin__field[data-index=name] input"/> <element name="productSku" type="input" selector=".admin__field[data-index=sku] input"/> + <element name="enableProduct" type="checkbox" selector="input[name='product[status]']"/> <element name="productPrice" type="input" selector=".admin__field[data-index=price] input"/> <element name="advancedPricingLink" type="button" selector="button[data-index='advanced_pricing_button']"/> <element name="categoriesDropdown" type="multiselect" selector="div[data-index='category_ids']"/> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminProductStatusAttributeDisabledByDefaultTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminProductStatusAttributeDisabledByDefaultTest.xml new file mode 100644 index 0000000000000..f4c7ab28b22dd --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/Test/AdminProductStatusAttributeDisabledByDefaultTest.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="AdminProductStatusAttributeDisabledByDefaultTest"> + <annotations> + <title value="Verify the default option value for product Status attribute is set correctly during product creation"/> + <description value="The default option value for product Status attribute is set correctly during product creation"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-92424"/> + <group value="Catalog"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + </before> + <after> + <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttribute"/> + <waitForPageLoad stepKey="wait1"/> + <click selector="{{AdminProductAttributeGridSection.ResetFilter}}" stepKey="resetFiltersOnGrid1"/> + <fillField selector="{{AdminProductAttributeGridSection.GridFilterFrontEndLabel}}" userInput="Enable Product" stepKey="setAttributeLabel1"/> + <click selector="{{AdminProductAttributeGridSection.Search}}" stepKey="searchForAttributeFromTheGrid1"/> + <click selector="{{AdminProductAttributeGridSection.FirstRow}}" stepKey="clickOnAttributeRow1"/> + <waitForPageLoad stepKey="wait2"/> + <click selector="{{AdminNewAttributePanel.isDefault('1')}}" stepKey="resetOptionForStatusAttribute"/> + <click selector="{{AttributePropertiesSection.Save}}" stepKey="saveAttribute1"/> + <waitForPageLoad stepKey="waitForSaveAttribute1"/> + <actionGroup ref="ClearCacheActionGroup" stepKey="clearCache1"/> + + <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + </after> + <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttribute"/> + <waitForPageLoad stepKey="wait1"/> + <click selector="{{AdminProductAttributeGridSection.ResetFilter}}" stepKey="resetFiltersOnGrid"/> + <fillField selector="{{AdminProductAttributeGridSection.GridFilterFrontEndLabel}}" userInput="Enable Product" stepKey="setAttributeLabel"/> + <click selector="{{AdminProductAttributeGridSection.Search}}" stepKey="searchForAttributeFromTheGrid"/> + <click selector="{{AdminProductAttributeGridSection.FirstRow}}" stepKey="clickOnAttributeRow"/> + <waitForPageLoad stepKey="wait2"/> + <click selector="{{AdminNewAttributePanel.isDefault('2')}}" stepKey="chooseDisabledOptionForStatus"/> + <click selector="{{AttributePropertiesSection.Save}}" stepKey="saveAttribute"/> + <waitForPageLoad stepKey="waitForAttributeToSave"/> + <actionGroup ref="ClearCacheActionGroup" stepKey="clearCache"/> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> + <waitForPageLoad time="30" stepKey="waitForProductGridPageToLoad"/> + <click selector="{{AdminProductGridActionSection.addProductToggle}}" stepKey="clickOnAddProductDropdown"/> + <click selector="{{AdminProductGridActionSection.addSimpleProduct}}" stepKey="clickOnAddSimpleProduct"/> + <waitForPageLoad stepKey="waitForProductEditToLoad"/> + <dontSeeCheckboxIsChecked selector="{{AdminProductFormSection.enableProduct}}" stepKey="dontSeeCheckboxEnableProductIsChecked"/> + + </test> +</tests> \ No newline at end of file From c2a1f25dbc9f92d989111f88f851310bba504f3e Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko <skovalenko@magento.com> Date: Mon, 21 May 2018 18:21:25 +0300 Subject: [PATCH 0987/2023] MAGETWO-91608: SEO-friendly URL for category page not working --- .../Catalog/Controller/Adminhtml/Category.php | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category.php index 13c4353e65204..1272043743688 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category.php @@ -3,8 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Controller\Adminhtml; +use Magento\Store\Model\Store; + /** * Catalog category controller */ @@ -34,6 +38,22 @@ public function __construct( parent::__construct($context); } + /** + * Resolve store id + * + * Tries to take store id from store HTTP parameter, if can`t find it, try to dig into store_id + * If param is absent in store_id too, take default one + * @see Store + * + * @return int + */ + private function resolveStoreId() : int + { + $storeId = $this->getRequest()->getParam('store', false); + $storeId = $storeId === false ? $this->getRequest()->getParam('store_id', Store::DEFAULT_STORE_ID) : $storeId; + return (int) $storeId; + } + /** * Initialize requested category and put it into registry. * Root category can be returned, if inappropriate store/category is specified @@ -44,7 +64,7 @@ public function __construct( protected function _initCategory($getRootInstead = false) { $categoryId = $this->resolveCategoryId(); - $storeId = (int)$this->getRequest()->getParam('store'); + $storeId = $this->resolveStoreId(); $category = $this->_objectManager->create(\Magento\Catalog\Model\Category::class); $category->setStoreId($storeId); From a8da48564deac6acbafe2d143892ab6e5861e831 Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko <skovalenko@magento.com> Date: Tue, 29 May 2018 11:52:22 +0300 Subject: [PATCH 0988/2023] MAGETWO-91608: SEO-friendly URL for category page not working --- app/code/Magento/Catalog/Controller/Adminhtml/Category.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Category.php b/app/code/Magento/Catalog/Controller/Adminhtml/Category.php index 1272043743688..88c371cb179f9 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Category.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Category.php @@ -41,17 +41,14 @@ public function __construct( /** * Resolve store id * - * Tries to take store id from store HTTP parameter, if can`t find it, try to dig into store_id - * If param is absent in store_id too, take default one + * Tries to take store id from store HTTP parameter * @see Store * * @return int */ private function resolveStoreId() : int { - $storeId = $this->getRequest()->getParam('store', false); - $storeId = $storeId === false ? $this->getRequest()->getParam('store_id', Store::DEFAULT_STORE_ID) : $storeId; - return (int) $storeId; + return (int) $this->getRequest()->getParam('store_id', Store::DEFAULT_STORE_ID); } /** From cd0a7b4ebbb0fc67dd03a77e9a5dbfa7de1ac1c4 Mon Sep 17 00:00:00 2001 From: Chirag Matholiya <chirag@wagento.com> Date: Tue, 5 Jun 2018 09:41:04 +0530 Subject: [PATCH 0989/2023] Removed unnecessary css. --- .../Magento/luma/web/css/source/_actions-toolbar.less | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/design/frontend/Magento/luma/web/css/source/_actions-toolbar.less b/app/design/frontend/Magento/luma/web/css/source/_actions-toolbar.less index 096b93675a92c..d81d0a8388a78 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_actions-toolbar.less +++ b/app/design/frontend/Magento/luma/web/css/source/_actions-toolbar.less @@ -22,10 +22,6 @@ &:last-child { margin-bottom: 0; } - - &.primary { - // &:extend(.abs-button-l all); - } } &:last-child { From 9fa64255f77609f8b845f3d0b9f503e19a3a6828 Mon Sep 17 00:00:00 2001 From: hitesh-wagento <hitesh@wagento.com> Date: Mon, 4 Jun 2018 11:40:13 +0530 Subject: [PATCH 0990/2023] --- .../frontend/Magento/luma/web/css/source/_forms.less | 4 ---- .../frontend/Magento/luma/web/css/source/_theme.less | 7 +++++++ lib/web/css/source/lib/variables/_forms.less | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/design/frontend/Magento/luma/web/css/source/_forms.less b/app/design/frontend/Magento/luma/web/css/source/_forms.less index 1c9ffb1606b26..7c5027aef113b 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_forms.less +++ b/app/design/frontend/Magento/luma/web/css/source/_forms.less @@ -91,11 +91,7 @@ .select-styling() { .lib-css(appearance, none, 1); appearance: none; - background: @select__background url('../images/select-bg.svg') no-repeat 100% 45%; background-size: 30px 60px; - border: 1px solid @border-color__base; - height: 32px; - padding-right: 25px; text-indent: .01em; text-overflow: ''; diff --git a/app/design/frontend/Magento/luma/web/css/source/_theme.less b/app/design/frontend/Magento/luma/web/css/source/_theme.less index b94ffc08b77ec..957e622d6a0bb 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_theme.less +++ b/app/design/frontend/Magento/luma/web/css/source/_theme.less @@ -166,6 +166,13 @@ // Forms // --------------------------------------------- + +// Select +@select__background: @form-element-input__background url('../images/select-bg.svg') no-repeat 100% 45%; +@select__border: 1px solid @border-color__base; +@select__height: 32px; +@select__padding: 4px 25px @indent__xs @indent__s; + // Form fieldset @form-fieldset-legend__font-size: 18px; @form-fieldset-legend__font-weight: @font-weight__light; diff --git a/lib/web/css/source/lib/variables/_forms.less b/lib/web/css/source/lib/variables/_forms.less index 69d0146fb3555..fff6141c67fd5 100644 --- a/lib/web/css/source/lib/variables/_forms.less +++ b/lib/web/css/source/lib/variables/_forms.less @@ -121,7 +121,7 @@ @select__disabled__font-style: @form-element-input__disabled__font-style; // Focus state -@select__focus__background: @form-element-input__focus__background; +@select__focus__background: false; @select__focus__border: @form-element-input__focus__border; @select__focus__color: @form-element-input__focus__color; @select__focus__font-style: @form-element-input__focus__font-style; From 27e9d2f406c7fb8d3c5391db86ca97917e30b4bb Mon Sep 17 00:00:00 2001 From: Daniel Ruf <daniel.ruf@ueberbit.de> Date: Thu, 17 May 2018 18:20:52 +0200 Subject: [PATCH 0991/2023] fix: support multiple minisearch widget instances --- app/code/Magento/Search/view/frontend/web/form-mini.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Search/view/frontend/web/form-mini.js b/app/code/Magento/Search/view/frontend/web/form-mini.js index de16305bbbe8d..3ab44c2595de9 100644 --- a/app/code/Magento/Search/view/frontend/web/form-mini.js +++ b/app/code/Magento/Search/view/frontend/web/form-mini.js @@ -55,7 +55,7 @@ define([ this.autoComplete = $(this.options.destinationSelector); this.searchForm = $(this.options.formSelector); this.submitBtn = this.searchForm.find(this.options.submitBtn)[0]; - this.searchLabel = $(this.options.searchLabel); + this.searchLabel = this.searchForm.find(this.options.searchLabel); this.isExpandable = this.options.isExpandable; _.bindAll(this, '_onKeyDown', '_onPropertyChange', '_onSubmit'); From 7a3d351a5e4aa22ebe00e06cac45d4d23bdd2e31 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Tue, 5 Jun 2018 09:11:05 +0300 Subject: [PATCH 0992/2023] MAGETWO-90764: [2.3.0] Cannot cancel orders with an expired authorization for Braintree --- .../Gateway/Response/CancelDetailsHandler.php | 43 +++++ .../Braintree/Gateway/SubjectReader.php | 9 +- .../Validator/CancelResponseValidator.php | 88 +++++++++ .../Response/CancelDetailsHandlerTest.php | 61 ++++++ .../Test/Unit/Gateway/SubjectReaderTest.php | 98 ++++++++-- .../Validator/CancelResponseValidatorTest.php | 179 ++++++++++++++++++ app/code/Magento/Braintree/etc/di.xml | 14 +- 7 files changed, 473 insertions(+), 19 deletions(-) create mode 100644 app/code/Magento/Braintree/Gateway/Response/CancelDetailsHandler.php create mode 100644 app/code/Magento/Braintree/Gateway/Validator/CancelResponseValidator.php create mode 100644 app/code/Magento/Braintree/Test/Unit/Gateway/Response/CancelDetailsHandlerTest.php create mode 100644 app/code/Magento/Braintree/Test/Unit/Gateway/Validator/CancelResponseValidatorTest.php diff --git a/app/code/Magento/Braintree/Gateway/Response/CancelDetailsHandler.php b/app/code/Magento/Braintree/Gateway/Response/CancelDetailsHandler.php new file mode 100644 index 0000000000000..3d6ed025791bf --- /dev/null +++ b/app/code/Magento/Braintree/Gateway/Response/CancelDetailsHandler.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Braintree\Gateway\Response; + +use Magento\Braintree\Gateway\SubjectReader; +use Magento\Payment\Gateway\Response\HandlerInterface; +use Magento\Sales\Model\Order\Payment; + +/** + * Handles response details for order cancellation request. + */ +class CancelDetailsHandler implements HandlerInterface +{ + /** + * @var SubjectReader + */ + private $subjectReader; + + /** + * @param SubjectReader $subjectReader + */ + public function __construct(SubjectReader $subjectReader) + { + $this->subjectReader = $subjectReader; + } + + /** + * @inheritdoc + */ + public function handle(array $handlingSubject, array $response) + { + $paymentDO = $this->subjectReader->readPayment($handlingSubject); + /** @var Payment $orderPayment */ + $orderPayment = $paymentDO->getPayment(); + $orderPayment->setIsTransactionClosed(true); + $orderPayment->setShouldCloseParentTransaction(true); + } +} diff --git a/app/code/Magento/Braintree/Gateway/SubjectReader.php b/app/code/Magento/Braintree/Gateway/SubjectReader.php index d5dc43a4c5e34..7cf00233e7f8f 100644 --- a/app/code/Magento/Braintree/Gateway/SubjectReader.php +++ b/app/code/Magento/Braintree/Gateway/SubjectReader.php @@ -43,19 +43,20 @@ public function readPayment(array $subject) } /** - * Reads transaction from subject + * Reads transaction from the subject. * * @param array $subject - * @return \Braintree\Transaction + * @return Transaction + * @throws \InvalidArgumentException if the subject doesn't contain transaction details. */ public function readTransaction(array $subject) { if (!isset($subject['object']) || !is_object($subject['object'])) { - throw new \InvalidArgumentException('Response object does not exist'); + throw new \InvalidArgumentException('Response object does not exist.'); } if (!isset($subject['object']->transaction) - && !$subject['object']->transaction instanceof Transaction + || !$subject['object']->transaction instanceof Transaction ) { throw new \InvalidArgumentException('The object is not a class \Braintree\Transaction.'); } diff --git a/app/code/Magento/Braintree/Gateway/Validator/CancelResponseValidator.php b/app/code/Magento/Braintree/Gateway/Validator/CancelResponseValidator.php new file mode 100644 index 0000000000000..3c4380747fab0 --- /dev/null +++ b/app/code/Magento/Braintree/Gateway/Validator/CancelResponseValidator.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Braintree\Gateway\Validator; + +use Braintree\Error\ErrorCollection; +use Braintree\Error\Validation; +use Magento\Payment\Gateway\Validator\AbstractValidator; +use Magento\Payment\Gateway\Validator\ResultInterface; +use Magento\Payment\Gateway\Validator\ResultInterfaceFactory; +use Magento\Braintree\Gateway\SubjectReader; + +/** + * This validator decorates the general response validator to handle specific cases like + * an expired or already voided on Braintree side authorization transaction. + */ +class CancelResponseValidator extends AbstractValidator +{ + /** + * @var int + */ + private static $acceptableTransactionCode = 91504; + + /** + * @var GeneralResponseValidator + */ + private $generalResponseValidator; + + /** + * @var SubjectReader + */ + private $subjectReader; + + /** + * @param ResultInterfaceFactory $resultFactory + * @param GeneralResponseValidator $generalResponseValidator + * @param SubjectReader $subjectReader + */ + public function __construct( + ResultInterfaceFactory $resultFactory, + GeneralResponseValidator $generalResponseValidator, + SubjectReader $subjectReader + ) { + parent::__construct($resultFactory); + $this->generalResponseValidator = $generalResponseValidator; + $this->subjectReader = $subjectReader; + } + + /** + * @inheritdoc + */ + public function validate(array $validationSubject): ResultInterface + { + $result = $this->generalResponseValidator->validate($validationSubject); + if (!$result->isValid()) { + $response = $this->subjectReader->readResponseObject($validationSubject); + if ($this->isErrorAcceptable($response->errors)) { + $result = $this->createResult(true, [__('Transaction is cancelled offline.')]); + } + } + + return $result; + } + + /** + * Checks if error collection has an acceptable error code. + * + * @param ErrorCollection $errorCollection + * @return bool + */ + private function isErrorAcceptable(ErrorCollection $errorCollection): bool + { + $errors = $errorCollection->deepAll(); + // there is should be only one acceptable error + if (count($errors) > 1) { + return false; + } + + /** @var Validation $error */ + $error = array_pop($errors); + + return (int)$error->code === self::$acceptableTransactionCode; + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Response/CancelDetailsHandlerTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/CancelDetailsHandlerTest.php new file mode 100644 index 0000000000000..2fa3d2ea65836 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Response/CancelDetailsHandlerTest.php @@ -0,0 +1,61 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Braintree\Test\Unit\Gateway\Response; + +use Magento\Braintree\Gateway\Response\CancelDetailsHandler; +use Magento\Braintree\Gateway\SubjectReader; +use Magento\Payment\Gateway\Data\OrderAdapterInterface; +use Magento\Payment\Gateway\Data\PaymentDataObject; +use Magento\Sales\Model\Order\Payment; +use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +/** + * Tests \Magento\Braintree\Gateway\Response\CancelDetailsHandler. + */ +class CancelDetailsHandlerTest extends TestCase +{ + /** + * @var CancelDetailsHandler + */ + private $handler; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->handler = new CancelDetailsHandler(new SubjectReader()); + } + + /** + * Checks a case when cancel handler closes the current and parent transactions. + * + * @return void + */ + public function testHandle(): void + { + /** @var OrderAdapterInterface|MockObject $order */ + $order = $this->getMockForAbstractClass(OrderAdapterInterface::class); + /** @var Payment|MockObject $payment */ + $payment = $this->getMockBuilder(Payment::class) + ->disableOriginalConstructor() + ->setMethods(['setOrder']) + ->getMock(); + + $paymentDO = new PaymentDataObject($order, $payment); + $response = [ + 'payment' => $paymentDO, + ]; + + $this->handler->handle($response, []); + + self::assertTrue($payment->getIsTransactionClosed(), 'The current transaction should be closed.'); + self::assertTrue($payment->getShouldCloseParentTransaction(), 'The parent transaction should be closed.'); + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/SubjectReaderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/SubjectReaderTest.php index 4213acc8b4ff0..fdf3c583188af 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/SubjectReaderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/SubjectReaderTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Braintree\Test\Unit\Gateway; +use Braintree\Result\Successful; use Braintree\Transaction; use Magento\Braintree\Gateway\SubjectReader; @@ -18,6 +19,9 @@ class SubjectReaderTest extends \PHPUnit\Framework\TestCase */ private $subjectReader; + /** + * @inheritdoc + */ protected function setUp() { $this->subjectReader = new SubjectReader(); @@ -27,67 +31,137 @@ protected function setUp() * @covers \Magento\Braintree\Gateway\SubjectReader::readCustomerId * @expectedException \InvalidArgumentException * @expectedExceptionMessage The "customerId" field does not exists + * @return void */ - public function testReadCustomerIdWithException() + public function testReadCustomerIdWithException(): void { $this->subjectReader->readCustomerId([]); } /** * @covers \Magento\Braintree\Gateway\SubjectReader::readCustomerId + * @return void */ - public function testReadCustomerId() + public function testReadCustomerId(): void { $customerId = 1; - static::assertEquals($customerId, $this->subjectReader->readCustomerId(['customer_id' => $customerId])); + $this->assertEquals($customerId, $this->subjectReader->readCustomerId(['customer_id' => $customerId])); } /** * @covers \Magento\Braintree\Gateway\SubjectReader::readPublicHash * @expectedException \InvalidArgumentException * @expectedExceptionMessage The "public_hash" field does not exists + * @return void */ - public function testReadPublicHashWithException() + public function testReadPublicHashWithException(): void { $this->subjectReader->readPublicHash([]); } /** * @covers \Magento\Braintree\Gateway\SubjectReader::readPublicHash + * @return void */ - public function testReadPublicHash() + public function testReadPublicHash(): void { $hash = 'fj23djf2o1fd'; - static::assertEquals($hash, $this->subjectReader->readPublicHash(['public_hash' => $hash])); + $this->assertEquals($hash, $this->subjectReader->readPublicHash(['public_hash' => $hash])); } /** * @covers \Magento\Braintree\Gateway\SubjectReader::readPayPal * @expectedException \InvalidArgumentException * @expectedExceptionMessage Transaction has't paypal attribute + * @return void */ - public function testReadPayPalWithException() + public function testReadPayPalWithException(): void { $transaction = Transaction::factory([ - 'id' => 'u38rf8kg6vn' + 'id' => 'u38rf8kg6vn', ]); $this->subjectReader->readPayPal($transaction); } /** * @covers \Magento\Braintree\Gateway\SubjectReader::readPayPal + * @return void */ - public function testReadPayPal() + public function testReadPayPal(): void { $paypal = [ 'paymentId' => '3ek7dk7fn0vi1', - 'payerEmail' => 'payer@example.com' + 'payerEmail' => 'payer@example.com', ]; $transaction = Transaction::factory([ 'id' => '4yr95vb', - 'paypal' => $paypal + 'paypal' => $paypal, ]); - static::assertEquals($paypal, $this->subjectReader->readPayPal($transaction)); + $this->assertEquals($paypal, $this->subjectReader->readPayPal($transaction)); + } + + /** + * Checks a case when subject reader retrieves successful Braintree transaction. + * + * @return void + */ + public function testReadTransaction(): void + { + $transaction = Transaction::factory(['id' => 1]); + $response = [ + 'object' => new Successful($transaction, 'transaction'), + ]; + $actual = $this->subjectReader->readTransaction($response); + + $this->assertSame($transaction, $actual); + } + + /** + * Checks a case when subject reader retrieves invalid data instead transaction details. + * + * @param array $response + * @param string $expectedMessage + * @dataProvider invalidTransactionResponseDataProvider + * @expectedException \InvalidArgumentException + * @return void + */ + public function testReadTransactionWithInvalidResponse(array $response, string $expectedMessage):void + { + $this->expectExceptionMessage($expectedMessage); + $this->subjectReader->readTransaction($response); + } + + /** + * Gets list of variations with invalid subject data. + * + * @return array + */ + public function invalidTransactionResponseDataProvider(): array + { + $transaction = new \stdClass(); + $response = new \stdClass(); + $response->transaction = $transaction; + + return [ + [ + 'response' => [ + 'object' => [], + ], + 'expectedMessage' => 'Response object does not exist.', + ], + [ + 'response' => [ + 'object' => new \stdClass(), + ], + 'expectedMessage' => 'The object is not a class \Braintree\Transaction.', + ], + [ + 'response' => [ + 'object' => $response, + ], + 'expectedMessage' => 'The object is not a class \Braintree\Transaction.', + ], + ]; } } diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/CancelResponseValidatorTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/CancelResponseValidatorTest.php new file mode 100644 index 0000000000000..54d8151f7819f --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Validator/CancelResponseValidatorTest.php @@ -0,0 +1,179 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Braintree\Test\Unit\Gateway\Validator; + +use Braintree\Result\Error; +use Magento\Braintree\Gateway\Validator\CancelResponseValidator; +use PHPUnit\Framework\TestCase; +use Magento\Braintree\Gateway\Validator\GeneralResponseValidator; +use Magento\Braintree\Gateway\SubjectReader; +use Magento\Payment\Gateway\Validator\ResultInterface; +use Magento\Payment\Gateway\Validator\ResultInterfaceFactory; +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +/** + * Tests \Magento\Braintree\Gateway\Validator\CancelResponseValidator class. + */ +class CancelResponseValidatorTest extends TestCase +{ + /** + * @var CancelResponseValidator + */ + private $validator; + + /** + * @var GeneralResponseValidator|MockObject + */ + private $generalValidator; + + /** + * @var ResultInterfaceFactory|MockObject + */ + private $resultFactory; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->generalValidator = $this->getMockBuilder(GeneralResponseValidator::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->resultFactory = $this->getMockBuilder(ResultInterfaceFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->validator = new CancelResponseValidator( + $this->resultFactory, + $this->generalValidator, + new SubjectReader() + ); + } + + /** + * Checks a case when response is successful and additional validation doesn't needed. + * + * @return void + */ + public function testValidateSuccessfulTransaction(): void + { + /** @var ResultInterface|MockObject $result */ + $result = $this->getMockForAbstractClass(ResultInterface::class); + $result->method('isValid')->willReturn(true); + $this->generalValidator->method('validate')->willReturn($result); + $actual = $this->validator->validate([]); + + $this->assertSame($result, $actual); + } + + /** + * Checks a case when response contains error related to expired authorization transaction and + * validator should return positive result. + * + * @return void + */ + public function testValidateExpiredTransaction(): void + { + /** @var ResultInterface|MockObject $result */ + $result = $this->getMockForAbstractClass(ResultInterface::class); + $result->method('isValid')->willReturn(false); + $this->generalValidator->method('validate')->willReturn($result); + + $expected = $this->getMockForAbstractClass(ResultInterface::class); + $expected->method('isValid')->willReturn(true); + $this->resultFactory->method('create') + ->with( + [ + 'isValid' => true, + 'failsDescription' => ['Transaction is cancelled offline.'], + 'errorCodes' => [] + ] + )->willReturn($expected); + + $errors = [ + 'errors' => [ + [ + 'code' => 91504, + 'message' => 'Transaction can only be voided if status is authorized.', + ] + ], + ]; + $buildSubject = [ + 'response' => [ + 'object' => new Error(['errors' => $errors]), + ], + ]; + + $actual = $this->validator->validate($buildSubject); + + $this->assertSame($expected, $actual); + } + + /** + * Checks a case when response contains multiple errors and validator should return negative result. + * + * @param array $responseErrors + * @return void + * @dataProvider getErrorsDataProvider + */ + public function testValidateWithMultipleErrors(array $responseErrors): void + { + /** @var ResultInterface|MockObject $result */ + $result = $this->getMockForAbstractClass(ResultInterface::class); + $result->method('isValid')->willReturn(false); + + $this->generalValidator->method('validate')->willReturn($result); + + $this->resultFactory->expects($this->never())->method('create'); + + $errors = [ + 'errors' => $responseErrors, + ]; + $buildSubject = [ + 'response' => [ + 'object' => new Error(['errors' => $errors]), + ] + ]; + + $actual = $this->validator->validate($buildSubject); + + $this->assertSame($result, $actual); + } + + /** + * Gets list of errors variations. + * + * @return array + */ + public function getErrorsDataProvider(): array + { + return [ + [ + 'errors' => [ + [ + 'code' => 91734, + 'message' => 'Credit card type is not accepted by this merchant account.', + ], + [ + 'code' => 91504, + 'message' => 'Transaction can only be voided if status is authorized.', + ], + ], + ], + [ + 'errors' => [ + [ + 'code' => 91734, + 'message' => 'Credit card type is not accepted by this merchant account.', + ], + ], + ], + ]; + } +} diff --git a/app/code/Magento/Braintree/etc/di.xml b/app/code/Magento/Braintree/etc/di.xml index 2bb4cea6742d6..290fb5be58f34 100644 --- a/app/code/Magento/Braintree/etc/di.xml +++ b/app/code/Magento/Braintree/etc/di.xml @@ -133,8 +133,8 @@ <item name="vault_capture" xsi:type="string">BraintreeVaultCaptureCommand</item> <item name="void" xsi:type="string">BraintreeVoidCommand</item> <item name="refund" xsi:type="string">BraintreeRefundCommand</item> - <item name="cancel" xsi:type="string">BraintreeVoidCommand</item> - <item name="deny_payment" xsi:type="string">BraintreeVoidCommand</item> + <item name="cancel" xsi:type="string">Magento\Braintree\Gateway\CancelCommand</item> + <item name="deny_payment" xsi:type="string">Magento\Braintree\Gateway\CancelCommand</item> </argument> </arguments> </virtualType> @@ -150,7 +150,7 @@ <item name="vault_capture" xsi:type="string">BraintreeVaultCaptureCommand</item> <item name="void" xsi:type="string">BraintreeVoidCommand</item> <item name="refund" xsi:type="string">BraintreeRefundCommand</item> - <item name="cancel" xsi:type="string">BraintreeVoidCommand</item> + <item name="cancel" xsi:type="string">Magento\Braintree\Gateway\CancelCommand</item> </argument> </arguments> </virtualType> @@ -505,6 +505,14 @@ </arguments> </virtualType> <!-- END Void Command --> + <!-- Cancel Command --> + <virtualType name="Magento\Braintree\Gateway\CancelCommand" type="BraintreeVoidCommand"> + <arguments> + <argument name="handler" xsi:type="object">Magento\Braintree\Gateway\Response\CancelDetailsHandler</argument> + <argument name="validator" xsi:type="object">Magento\Braintree\Gateway\Validator\CancelResponseValidator</argument> + </arguments> + </virtualType> + <!-- END Cancel Command --> <!-- Refund Command --> <virtualType name="BraintreeRefundCommand" type="Magento\Payment\Gateway\Command\GatewayCommand"> From b45ef300b01543490511d6f9878bdd4b4379d1f6 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 5 Jun 2018 10:18:37 +0300 Subject: [PATCH 0993/2023] MAGETWO-90808: [Performance] Customer Import check data does not complete --- .../Model/Import/Address.php | 8 ---- .../ResourceModel/Import/Customer/Storage.php | 38 ------------------- 2 files changed, 46 deletions(-) diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Address.php b/app/code/Magento/CustomerImportExport/Model/Import/Address.php index 5ddf18031c7bc..e1345edcf146d 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Address.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Address.php @@ -168,14 +168,6 @@ class Address extends AbstractCustomer */ protected $_attributeCollection; - /** - * Collection of existent addresses - * - * @var \Magento\Customer\Model\ResourceModel\Address\Collection - * @deprecated - */ - protected $_addressCollection; - /** * Store imported row primary keys * diff --git a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php index 03c75297343c3..f779505a38011 100644 --- a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php +++ b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php @@ -15,22 +15,6 @@ class Storage { - /** - * Flag to not load collection more than one time - * - * @var bool - * @deprecated - */ - protected $_isCollectionLoaded = false; - - /** - * Customer collection - * - * @var \Magento\Customer\Model\ResourceModel\Customer\Collection - * @deprecated - */ - protected $_customerCollection; - /** * Existing customers information. In form of: * @@ -84,28 +68,6 @@ public function __construct( $this->customerCollectionFactory = $collectionFactory; } - /** - * Load needed data from customer collection - * - * @return void - * @deprecated - * @see prepareCustomers - */ - public function load() - { - if ($this->_isCollectionLoaded == false) { - $connection = $this->_customerCollection->getConnection(); - $select = $connection->select(); - $select->from($this->_customerCollection->getMainTable(), ['entity_id', 'website_id', 'email']); - $results = $connection->fetchAll($select); - foreach ($results as $customer) { - $this->addCustomerByArray($customer); - } - - $this->_isCollectionLoaded = true; - } - } - /** * Create new collection to load customer data with proper filters. * From 75b821d1f1dcbd22b55597e47e0eb2af5e188289 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 5 Jun 2018 10:37:06 +0300 Subject: [PATCH 0994/2023] MAGETWO-90808: [Performance] Customer Import check data does not complete --- .../Test/Unit/Model/Import/CustomerCompositeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php index 983e20eb77d80..1b900c2139588 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php @@ -265,7 +265,7 @@ protected function _getCustomerEntityMock() /** * @return Address|\PHPUnit_Framework_MockObject_MockObject */ - protected function _getAddressEntityMock() + private function _getAddressEntityMock() { $addressEntity = $this->createMock(Address::class); From 279655ad94a9de13d8d953d1f1d205cb5de9a0ac Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 5 Jun 2018 11:15:13 +0300 Subject: [PATCH 0995/2023] MAGETWO-90787: Swagger does not render correctly for many POST/PUT operations --- .../frontend/layout/swagger_index_index.xml | 35 +- .../frontend/templates/swagger-ui/index.phtml | 39 +- .../frontend/web/swagger-ui/css/print.css | 1172 - .../frontend/web/swagger-ui/css/reset.css | 125 - .../frontend/web/swagger-ui/css/screen.css | 1279 - .../frontend/web/swagger-ui/css/style.css | 270 +- .../web/swagger-ui/css/swagger-ui.css | 2 + .../web/swagger-ui/css/typography.css | 26 - .../fonts/droid-sans-v6-latin-700.eot | Bin 22922 -> 0 bytes .../fonts/droid-sans-v6-latin-700.svg | 411 - .../fonts/droid-sans-v6-latin-700.ttf | Bin 40513 -> 0 bytes .../fonts/droid-sans-v6-latin-700.woff | Bin 25992 -> 0 bytes .../fonts/droid-sans-v6-latin-700.woff2 | Bin 11480 -> 0 bytes .../fonts/droid-sans-v6-latin-regular.eot | Bin 22008 -> 0 bytes .../fonts/droid-sans-v6-latin-regular.svg | 403 - .../fonts/droid-sans-v6-latin-regular.ttf | Bin 39069 -> 0 bytes .../fonts/droid-sans-v6-latin-regular.woff | Bin 24868 -> 0 bytes .../fonts/droid-sans-v6-latin-regular.woff2 | Bin 11304 -> 0 bytes .../web/swagger-ui/images/explorer_icons.png | Bin 2474 -> 0 bytes .../web/swagger-ui/images/favicon-16x16.png | Bin 449 -> 0 bytes .../web/swagger-ui/images/favicon-32x32.png | Bin 1141 -> 0 bytes .../web/swagger-ui/images/favicon.ico | Bin 5430 -> 0 bytes .../web/swagger-ui/images/pet_store_api.png | Bin 637 -> 0 bytes .../web/swagger-ui/images/throbber.gif | Bin 6122 -> 0 bytes .../web/swagger-ui/images/wordnik_api.png | Bin 672 -> 0 bytes .../web/swagger-ui/js/lang/translator.js | 13 +- .../web/swagger-ui/js/lib/backbone-min.js | 15 - .../js/lib/handlebars.min-v4.0.10.js | 29 - .../swagger-ui/js/lib/highlight.9.1.0.pack.js | 1 - .../js/lib/highlight.9.1.0.pack_extended.js | 1 - .../web/swagger-ui/js/lib/jquery-1.8.0.min.js | 2 - .../swagger-ui/js/lib/jquery.ba-bbq.min.js | 18 - .../swagger-ui/js/lib/jquery.slideto.min.js | 1 - .../swagger-ui/js/lib/jquery.wiggle.min.js | 8 - .../web/swagger-ui/js/lib/jsoneditor.min.js | 5 - .../web/swagger-ui/js/lib/lodash.min.js | 2 - .../frontend/web/swagger-ui/js/lib/marked.js | 1274 - .../js/lib/object-assign-pollyfill.js | 1 - .../web/swagger-ui/js/lib/swagger-oauth.js | 290 - .../web/swagger-ui/js/lib/underscore-min.js | 6 - .../web/swagger-ui/js/lib/underscore-min.map | 1 - .../web/swagger-ui/js/magento-swagger.js | 95 +- .../web/swagger-ui/js/swagger-ui-bundle.js | 99 + .../js/swagger-ui-standalone-preset.js | 13 + .../frontend/web/swagger-ui/js/swagger-ui.js | 25344 ---------------- .../Constraint/AssertApiInfoTitleOnPage.php | 2 +- .../AssertEndpointContentDisplay.php | 4 +- .../AssertServiceContentDisplay.php | 4 +- .../Swagger/Test/Page/SwaggerUiPage.php | 38 +- .../Test/Js/_files/blacklist/magento.txt | 16 +- 50 files changed, 274 insertions(+), 30770 deletions(-) delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/css/print.css delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/css/reset.css delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/css/screen.css create mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/css/swagger-ui.css delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/css/typography.css delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-700.eot delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-700.svg delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-700.ttf delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-700.woff delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-700.woff2 delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-regular.eot delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-regular.svg delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-regular.ttf delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-regular.woff delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/fonts/droid-sans-v6-latin-regular.woff2 delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/images/explorer_icons.png delete mode 100755 app/code/Magento/Swagger/view/frontend/web/swagger-ui/images/favicon-16x16.png delete mode 100755 app/code/Magento/Swagger/view/frontend/web/swagger-ui/images/favicon-32x32.png delete mode 100755 app/code/Magento/Swagger/view/frontend/web/swagger-ui/images/favicon.ico delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/images/pet_store_api.png delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/images/throbber.gif delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/images/wordnik_api.png delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/backbone-min.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/handlebars.min-v4.0.10.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/highlight.9.1.0.pack.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/highlight.9.1.0.pack_extended.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/jquery-1.8.0.min.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/jquery.ba-bbq.min.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/jquery.slideto.min.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/jquery.wiggle.min.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/jsoneditor.min.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/lodash.min.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/marked.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/object-assign-pollyfill.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/swagger-oauth.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/underscore-min.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/lib/underscore-min.map create mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/swagger-ui-bundle.js create mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/swagger-ui-standalone-preset.js delete mode 100644 app/code/Magento/Swagger/view/frontend/web/swagger-ui/js/swagger-ui.js diff --git a/app/code/Magento/Swagger/view/frontend/layout/swagger_index_index.xml b/app/code/Magento/Swagger/view/frontend/layout/swagger_index_index.xml index 345f063a7aaa3..f14df1c70a790 100644 --- a/app/code/Magento/Swagger/view/frontend/layout/swagger_index_index.xml +++ b/app/code/Magento/Swagger/view/frontend/layout/swagger_index_index.xml @@ -10,32 +10,18 @@ <title>Swagger UI - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + @@ -43,6 +29,7 @@ + diff --git a/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml b/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml index 27b3767f274bc..b20da68734579 100644 --- a/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml +++ b/app/code/Magento/Swagger/view/frontend/templates/swagger-ui/index.phtml @@ -12,11 +12,48 @@ * Modified by Magento, Modifications Copyright © Magento, Inc. All rights reserved. */ -/** @var \Magento\Swagger\Block\Index $block */ +/** @var \Magento\Swagger\Block\Index $block + * + * @codingStandardsIgnoreFile + */ $schemaUrl = $block->getSchemaUrl(); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +