From 924358042a2d970568007b00c0cd0f9239545fa7 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Fri, 18 Mar 2016 12:30:21 +0200 Subject: [PATCH 01/30] MAGETWO-50507: Exception error appears if Merchant resets "Product Attributes mass update" Admin form --- .../Product/Action/Attribute/Edit.php | 21 +- .../Product/Action/Attribute/EditTest.php | 191 ++++++++++++++++++ 2 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php index 8e4b59d396986..b16b9cb06d28e 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php @@ -53,8 +53,12 @@ public function __construct( */ public function execute() { - $collection = $this->filter->getCollection($this->collectionFactory->create()); - $this->attributeHelper->setProductIds($collection->getAllIds()); + $this->verifyNamespace(); + + if ($this->getRequest()->getParam('filters')) { + $collection = $this->filter->getCollection($this->collectionFactory->create()); + $this->attributeHelper->setProductIds($collection->getAllIds()); + } if (!$this->_validateProducts()) { return $this->resultRedirectFactory->create()->setPath('catalog/product/', ['_current' => true]); @@ -63,4 +67,17 @@ public function execute() $resultPage->getConfig()->getTitle()->prepend(__('Update Attributes')); return $resultPage; } + + /** + * Check if namespace is specified + * @return void + */ + private function verifyNamespace() + { + if (!$this->getRequest()->getParam('namespace')) { + $params = $this->getRequest()->getParams(); + $params['namespace'] = 'product_listing'; + $this->getRequest()->setParams($params); + } + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php new file mode 100644 index 0000000000000..4c268a8857674 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php @@ -0,0 +1,191 @@ +attributeHelper = $this->getMockBuilder('Magento\Catalog\Helper\Product\Edit\Action\Attribute') + ->setMethods(['getProductIds', 'setProductIds']) + ->disableOriginalConstructor()->getMock(); + + $this->resultRedirectFactory = $this->getMockBuilder('Magento\Backend\Model\View\Result\RedirectFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->filter = $this->getMockBuilder('Magento\Ui\Component\MassAction\Filter') + ->setMethods(['getCollection'])->disableOriginalConstructor()->getMock(); + + $this->collectionFactory = $this->getMockBuilder( + 'Magento\Catalog\Model\ResourceModel\Product\CollectionFactory' + )->setMethods(['create'])->disableOriginalConstructor()->getMock(); + + $this->resultPage = $this->getMockBuilder('Magento\Framework\View\Result\Page') + ->setMethods(['getConfig'])->disableOriginalConstructor()->getMock(); + + $resultPageFactory = $this->getMockBuilder('Magento\Framework\View\Result\PageFactory') + ->setMethods(['create'])->disableOriginalConstructor()->getMock(); + $resultPageFactory->expects($this->any())->method('create')->willReturn($this->resultPage); + + $this->prepareContext(); + + $this->object = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( + 'Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Edit', + [ + 'context' => $this->context, + 'attributeHelper' => $this->attributeHelper, + 'filter' => $this->filter, + 'resultPageFactory' => $resultPageFactory, + 'collectionFactory' => $this->collectionFactory + ] + ); + } + + private function prepareContext() + { + $this->request = $this->getMockBuilder('Magento\Framework\App\Request\Http') + ->setMethods(['getParam', 'getParams', 'setParams']) + ->disableOriginalConstructor()->getMock(); + + $objectManager = $this->getMock('Magento\Framework\ObjectManagerInterface'); + $product = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->setMethods(['isProductsHasSku']) + ->disableOriginalConstructor()->getMock(); + $product->expects($this->any())->method('isProductsHasSku') + ->with([1, 2, 3]) + ->willReturn(true); + $objectManager->expects($this->any())->method('create') + ->with('Magento\Catalog\Model\Product') + ->willReturn($product); + $messageManager = $this->getMockBuilder('\Magento\Framework\Message\ManagerInterface') + ->setMethods([]) + ->disableOriginalConstructor()->getMock(); + $messageManager->expects($this->any())->method('addError')->willReturn(true); + $this->context = $this->getMockBuilder('Magento\Backend\App\Action\Context') + ->setMethods(['getRequest', 'getObjectManager', 'getMessageManager', 'getResultRedirectFactory']) + ->disableOriginalConstructor()->getMock(); + $this->context->expects($this->any())->method('getRequest')->willReturn($this->request); + $this->context->expects($this->any())->method('getObjectManager')->willReturn($objectManager); + $this->context->expects($this->any())->method('getMessageManager')->willReturn($messageManager); + $this->context->expects($this->any())->method('getResultRedirectFactory') + ->willReturn($this->resultRedirectFactory); + } + + public function testExecutePageRequested() + { + $this->request->expects($this->any())->method('getParam')->willReturnMap( + [ + ['namespace', null, 'product_listing'], + ['filters', null, ['placeholder' => true]] + ] + ); + $this->request->expects($this->any())->method('getParams')->willReturn( + [ + 'namespace' => 'product_listing', + 'exclude' => true, + 'filters' => ['placeholder' => true] + ] + ); + + $this->attributeHelper->expects($this->any())->method('getProductIds')->willReturn([1, 2, 3]); + $this->attributeHelper->expects($this->any())->method('setProductIds')->with([1, 2, 3]); + + $collection = $this->getMockBuilder('Magento\Catalog\Model\ResourceModel\Product\Collection') + ->setMethods(['getAllIds']) + ->disableOriginalConstructor()->getMock(); + $collection->expects($this->any())->method('getAllIds')->willReturn([1, 2, 3]); + $this->filter->expects($this->any())->method('getCollection')->with($collection)->willReturn($collection); + $this->collectionFactory->expects($this->any())->method('create')->willReturn($collection); + + $title = $this->getMockBuilder('Magento\Framework\View\Page\Title') + ->setMethods(['prepend']) + ->disableOriginalConstructor()->getMock(); + $config = $this->getMockBuilder('Magento\Framework\View\Page\Config') + ->setMethods(['getTitle']) + ->disableOriginalConstructor()->getMock(); + $config->expects($this->any())->method('getTitle')->willReturn($title); + $this->resultPage->expects($this->any())->method('getConfig')->willReturn($config); + + $this->assertSame($this->resultPage, $this->object->execute()); + } + + public function testExecutePageReload() + { + $this->request->expects($this->any())->method('getParam')->willReturnMap( + [ + ['namespace', null, null], + ['filters', null, null] + ] + ); + $this->request->expects($this->any())->method('getParams')->willReturn([]); + + $this->attributeHelper->expects($this->any())->method('getProductIds')->willReturn([1, 2, 3]); + $this->attributeHelper->expects($this->any())->method('setProductIds')->with([1, 2, 3]); + + $title = $this->getMockBuilder('Magento\Framework\View\Page\Title') + ->setMethods(['prepend']) + ->disableOriginalConstructor()->getMock(); + $config = $this->getMockBuilder('Magento\Framework\View\Page\Config') + ->setMethods(['getTitle']) + ->disableOriginalConstructor()->getMock(); + $config->expects($this->any())->method('getTitle')->willReturn($title); + $this->resultPage->expects($this->any())->method('getConfig')->willReturn($config); + + $this->assertSame($this->resultPage, $this->object->execute()); + } + + public function testExecutePageDirectAccess() + { + $this->request->expects($this->any())->method('getParam')->willReturnMap( + [ + ['namespace', null, null], + ['filters', null, null] + ] + ); + $this->request->expects($this->any())->method('getParams')->willReturn([]); + $this->attributeHelper->expects($this->any())->method('getProductIds')->willReturn(null); + + $resultRedirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect') + ->setMethods(['setPath']) + ->disableOriginalConstructor() + ->getMock(); + $resultRedirect->expects($this->any())->method('setPath') + ->with('catalog/product/', ['_current' => true]) + ->willReturnSelf(); + $this->resultRedirectFactory->expects($this->any()) + ->method('create') + ->willReturn($resultRedirect); + + $this->assertSame($resultRedirect, $this->object->execute()); + } +} From 562634f4df4394f417acad9d55cf8a9a9d417f90 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Mon, 21 Mar 2016 11:57:41 +0200 Subject: [PATCH 02/30] MAGETWO-50507: Exception error appears if Merchant resets "Product Attributes mass update" Admin form - CR changes --- .../Product/Action/Attribute/Edit.php | 15 ------------- .../Product/Action/Attribute/EditTest.php | 21 +++---------------- 2 files changed, 3 insertions(+), 33 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php index b16b9cb06d28e..38216ef98d2dd 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Edit.php @@ -53,8 +53,6 @@ public function __construct( */ public function execute() { - $this->verifyNamespace(); - if ($this->getRequest()->getParam('filters')) { $collection = $this->filter->getCollection($this->collectionFactory->create()); $this->attributeHelper->setProductIds($collection->getAllIds()); @@ -67,17 +65,4 @@ public function execute() $resultPage->getConfig()->getTitle()->prepend(__('Update Attributes')); return $resultPage; } - - /** - * Check if namespace is specified - * @return void - */ - private function verifyNamespace() - { - if (!$this->getRequest()->getParam('namespace')) { - $params = $this->getRequest()->getParams(); - $params['namespace'] = 'product_listing'; - $this->getRequest()->setParams($params); - } - } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php index 4c268a8857674..d329ec1aabafc 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php @@ -103,12 +103,7 @@ private function prepareContext() public function testExecutePageRequested() { - $this->request->expects($this->any())->method('getParam')->willReturnMap( - [ - ['namespace', null, 'product_listing'], - ['filters', null, ['placeholder' => true]] - ] - ); + $this->request->expects($this->any())->method('getParam')->with('filters')->willReturn(['placeholder' => true]); $this->request->expects($this->any())->method('getParams')->willReturn( [ 'namespace' => 'product_listing', @@ -141,12 +136,7 @@ public function testExecutePageRequested() public function testExecutePageReload() { - $this->request->expects($this->any())->method('getParam')->willReturnMap( - [ - ['namespace', null, null], - ['filters', null, null] - ] - ); + $this->request->expects($this->any())->method('getParam')->with('filters')->willReturn(null); $this->request->expects($this->any())->method('getParams')->willReturn([]); $this->attributeHelper->expects($this->any())->method('getProductIds')->willReturn([1, 2, 3]); @@ -166,12 +156,7 @@ public function testExecutePageReload() public function testExecutePageDirectAccess() { - $this->request->expects($this->any())->method('getParam')->willReturnMap( - [ - ['namespace', null, null], - ['filters', null, null] - ] - ); + $this->request->expects($this->any())->method('getParam')->with('filters')->willReturn(null); $this->request->expects($this->any())->method('getParams')->willReturn([]); $this->attributeHelper->expects($this->any())->method('getProductIds')->willReturn(null); From 6b3e7941f0946bc327d21ab8c11268b020cbbe06 Mon Sep 17 00:00:00 2001 From: Caleb Champlin Date: Fri, 19 Feb 2016 14:21:11 -0700 Subject: [PATCH 03/30] MDVA-260: GLOB_BRACE in Magento 2.0.4 - Ported commit e0ed4ba from develop: Fix support for GLOB_BRACE on non-GNU Linux systems --- .../Magento/Framework/App/Utility/Files.php | 13 +++++++------ .../Magento/Framework/Filesystem/Driver/File.php | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Utility/Files.php b/lib/internal/Magento/Framework/App/Utility/Files.php index c4173ae95c603..041875d3d0e98 100644 --- a/lib/internal/Magento/Framework/App/Utility/Files.php +++ b/lib/internal/Magento/Framework/App/Utility/Files.php @@ -9,6 +9,7 @@ use Magento\Framework\Component\ComponentRegistrar; use Magento\Framework\Component\DirSearch; use Magento\Framework\View\Design\Theme\ThemePackageList; +use Zend\Stdlib\Glob; /** * A helper to gather specific kind of files in Magento application @@ -1192,8 +1193,8 @@ public static function getFiles(array $dirPatterns, $fileNamePattern, $recursive $result = []; foreach ($dirPatterns as $oneDirPattern) { $oneDirPattern = str_replace('\\', '/', $oneDirPattern); - $entriesInDir = glob("{$oneDirPattern}/{$fileNamePattern}", GLOB_NOSORT | GLOB_BRACE); - $subDirs = glob("{$oneDirPattern}/*", GLOB_ONLYDIR | GLOB_NOSORT | GLOB_BRACE); + $entriesInDir = Glob::glob("{$oneDirPattern}/{$fileNamePattern}", Glob::GLOB_NOSORT | Glob::GLOB_BRACE); + $subDirs = Glob::glob("{$oneDirPattern}/*", Glob::GLOB_ONLYDIR | Glob::GLOB_NOSORT | Glob::GLOB_BRACE); $filesInDir = array_diff($entriesInDir, $subDirs); if ($recursive) { @@ -1212,10 +1213,10 @@ public static function getFiles(array $dirPatterns, $fileNamePattern, $recursive */ public function getDiConfigs($asDataSet = false) { - $primaryConfigs = glob(BP . '/app/etc/{di.xml,*/di.xml}', GLOB_BRACE); + $primaryConfigs = Glob::glob(BP . '/app/etc/{di.xml,*/di.xml}', Glob::GLOB_BRACE); $moduleConfigs = []; foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleDir) { - $moduleConfigs = array_merge($moduleConfigs, glob($moduleDir . '/etc/{di,*/di}.xml', GLOB_BRACE)); + $moduleConfigs = array_merge($moduleConfigs, Glob::glob($moduleDir . '/etc/{di,*/di}.xml', Glob::GLOB_BRACE)); } $configs = array_merge($primaryConfigs, $moduleConfigs); @@ -1456,7 +1457,7 @@ public function readLists($globPattern) * Note that glob() for directories will be returned as is, * but passing directory is supported by the tools (phpcpd, phpmd, phpcs) */ - $files = glob($this->getPathToSource() . '/' . $pattern, GLOB_BRACE); + $files = Glob::glob($this->getPathToSource() . '/' . $pattern, Glob::GLOB_BRACE); } else { throw new \UnexpectedValueException( "Incorrect pattern record '$pattern'. Supported formats: " @@ -1501,7 +1502,7 @@ private function getPathByComponentPattern($componentType, $componentName, $path } else { $componentDir = $this->componentRegistrar->getPath($type, $componentName); if (!empty($componentDir)) { - $files = array_merge($files, glob($componentDir . '/' . $pathPattern, GLOB_BRACE)); + $files = array_merge($files, Glob::glob($componentDir . '/' . $pathPattern, Glob::GLOB_BRACE)); } } } diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index 22f77a3484826..dfe180064bee2 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -9,6 +9,7 @@ use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Filesystem\DriverInterface; +use Zend\Stdlib\Glob; /** * Class File @@ -268,7 +269,7 @@ public function search($pattern, $path) { clearstatcache(); $globPattern = rtrim($path, '/') . '/' . ltrim($pattern, '/'); - $result = @glob($globPattern, GLOB_BRACE); + $result = @Glob::glob($globPattern, Glob::GLOB_BRACE); return is_array($result) ? $result : []; } From ba8f75d52fb7f90b132832e546ab1cf206ef2fd8 Mon Sep 17 00:00:00 2001 From: Arkadii Chyzhov Date: Thu, 3 Mar 2016 19:12:59 +0200 Subject: [PATCH 04/30] MAGETWO-50076: [GitHub] Fix support for GLOB_BRACE on non-GNU Linux systems #3490 - added wrapper for \Zend\Stdlib\Glob - replaced usages of \Zend\Stdlib\Glob with \Magento\Framework\Filesystem\Glob - replaced usages of php core function "glob" and constants GLOB_* with \Magento\Framework\Filesystem\Glob - adjusted code formatting --- .../Util/Generate/Factory/AbstractFactory.php | 3 +- .../Magento/TestFramework/Application.php | 5 +-- .../TestFramework/Bootstrap/Settings.php | 8 +++-- .../Magento/Test/Legacy/FilesystemTest.php | 3 +- .../Magento/Framework/App/Utility/Files.php | 23 +++++++------ .../Framework/Filesystem/Driver/File.php | 4 +-- .../Magento/Framework/Filesystem/Glob.php | 33 +++++++++++++++++++ 7 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 lib/internal/Magento/Framework/Filesystem/Glob.php diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Generate/Factory/AbstractFactory.php b/dev/tests/functional/lib/Magento/Mtf/Util/Generate/Factory/AbstractFactory.php index 8d6443846d98b..b0844503044ef 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Generate/Factory/AbstractFactory.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Generate/Factory/AbstractFactory.php @@ -8,6 +8,7 @@ namespace Magento\Mtf\Util\Generate\Factory; use Magento\Framework\Filesystem\DriverInterface; +use Magento\Framework\Filesystem\Glob; /** * Class AbstractFactory @@ -156,7 +157,7 @@ protected function collectItems($type) $pattern = $this->_getPattern($type, $location); - $filesIterator = glob($pattern, GLOB_BRACE); + $filesIterator = Glob::glob($pattern, Glob::GLOB_BRACE); foreach ($filesIterator as $filePath) { if (!is_dir($filePath)) { diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php index 0747b609af45b..a4b6d95a8337d 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Application.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php @@ -12,6 +12,7 @@ use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\App\DeploymentConfig\Reader; +use Magento\Framework\Filesystem\Glob; /** * Encapsulates application installation, initialization and uninstall @@ -491,9 +492,9 @@ public function install() */ private function copyAppConfigFiles() { - $globalConfigFiles = glob( + $globalConfigFiles = Glob::glob( $this->_globalConfigDir . '/{di.xml,vendor_path.php}', - GLOB_BRACE + Glob::GLOB_BRACE ); foreach ($globalConfigFiles as $file) { $targetFile = $this->_configDir . str_replace($this->_globalConfigDir, '', $file); diff --git a/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/Settings.php b/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/Settings.php index 6e956e7c17a97..f5bf041f623cf 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/Settings.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/Settings.php @@ -4,11 +4,13 @@ * See COPYING.txt for license details. */ +namespace Magento\TestFramework\Bootstrap; + +use Magento\Framework\Filesystem\Glob; + /** * Convenient access to the bootstrap settings */ -namespace Magento\TestFramework\Bootstrap; - class Settings { /** @@ -142,7 +144,7 @@ protected function _resolvePathPattern($pattern) $allPatterns = preg_split('/\s*;\s*/', trim($pattern), -1, PREG_SPLIT_NO_EMPTY); foreach ($allPatterns as $onePattern) { $onePattern = $this->_resolvePath($onePattern); - $files = glob($onePattern, GLOB_BRACE); + $files = Glob::glob($onePattern, Glob::GLOB_BRACE); $result = array_merge($result, $files); } return $result; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/FilesystemTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/FilesystemTest.php index c7d0394f07c1b..09cf6b711f4d0 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/FilesystemTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/FilesystemTest.php @@ -8,6 +8,7 @@ namespace Magento\Test\Legacy; use Magento\Framework\Component\ComponentRegistrar; +use Magento\Framework\Filesystem\Glob; class FilesystemTest extends \PHPUnit_Framework_TestCase { @@ -112,7 +113,7 @@ public function testObsoleteViewPaths() foreach ($pathsToCheck as $path => $allowed) { $allowedFiles = $allowed['allowed_files']; $allowedDirs = $allowed['allowed_dirs']; - $foundFiles = glob($path, GLOB_BRACE); + $foundFiles = Glob::glob($path, Glob::GLOB_BRACE); if (!$foundFiles) { $this->fail("Glob pattern returned empty result: {$path}"); } diff --git a/lib/internal/Magento/Framework/App/Utility/Files.php b/lib/internal/Magento/Framework/App/Utility/Files.php index 041875d3d0e98..ede7c32c5cffa 100644 --- a/lib/internal/Magento/Framework/App/Utility/Files.php +++ b/lib/internal/Magento/Framework/App/Utility/Files.php @@ -9,7 +9,7 @@ use Magento\Framework\Component\ComponentRegistrar; use Magento\Framework\Component\DirSearch; use Magento\Framework\View\Design\Theme\ThemePackageList; -use Zend\Stdlib\Glob; +use Magento\Framework\Filesystem\Glob; /** * A helper to gather specific kind of files in Magento application @@ -237,8 +237,8 @@ private function getPubFiles($flags) { if ($flags & self::INCLUDE_PUB_CODE) { return array_merge( - glob(BP . '/*.php', GLOB_NOSORT), - glob(BP . '/pub/*.php', GLOB_NOSORT) + Glob::glob(BP . '/*.php', Glob::GLOB_NOSORT), + Glob::glob(BP . '/pub/*.php', Glob::GLOB_NOSORT) ); } return []; @@ -951,10 +951,10 @@ protected function _parseModuleStatic($file) { foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $modulePath) { if (preg_match( - '/^' . preg_quote("{$modulePath}/", '/') . 'view\/([a-z]+)\/web\/(.+)$/i', - $file, - $matches - ) === 1 + '/^' . preg_quote("{$modulePath}/", '/') . 'view\/([a-z]+)\/web\/(.+)$/i', + $file, + $matches + ) === 1 ) { list(, $area, $filePath) = $matches; return [$area, '', '', $moduleName, $filePath, $file]; @@ -1192,7 +1192,7 @@ public static function getFiles(array $dirPatterns, $fileNamePattern, $recursive { $result = []; foreach ($dirPatterns as $oneDirPattern) { - $oneDirPattern = str_replace('\\', '/', $oneDirPattern); + $oneDirPattern = str_replace('\\', '/', $oneDirPattern); $entriesInDir = Glob::glob("{$oneDirPattern}/{$fileNamePattern}", Glob::GLOB_NOSORT | Glob::GLOB_BRACE); $subDirs = Glob::glob("{$oneDirPattern}/*", Glob::GLOB_ONLYDIR | Glob::GLOB_NOSORT | Glob::GLOB_BRACE); $filesInDir = array_diff($entriesInDir, $subDirs); @@ -1216,7 +1216,10 @@ public function getDiConfigs($asDataSet = false) $primaryConfigs = Glob::glob(BP . '/app/etc/{di.xml,*/di.xml}', Glob::GLOB_BRACE); $moduleConfigs = []; foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleDir) { - $moduleConfigs = array_merge($moduleConfigs, Glob::glob($moduleDir . '/etc/{di,*/di}.xml', Glob::GLOB_BRACE)); + $moduleConfigs = array_merge( + $moduleConfigs, + Glob::glob($moduleDir . '/etc/{di,*/di}.xml', Glob::GLOB_BRACE) + ); } $configs = array_merge($primaryConfigs, $moduleConfigs); @@ -1384,7 +1387,7 @@ public function getModulePhpFiles($module, $asDataSet = true) $key = __METHOD__ . "/{$module}"; if (!isset(self::$_cache[$key])) { $files = self::getFiles( - [$this->componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Magento_'. $module)], + [$this->componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Magento_' . $module)], '*.php' ); self::$_cache[$key] = $files; diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index dfe180064bee2..d19ea2efd6ef9 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -9,7 +9,7 @@ use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Filesystem\DriverInterface; -use Zend\Stdlib\Glob; +use Magento\Framework\Filesystem\Glob; /** * Class File @@ -269,7 +269,7 @@ public function search($pattern, $path) { clearstatcache(); $globPattern = rtrim($path, '/') . '/' . ltrim($pattern, '/'); - $result = @Glob::glob($globPattern, Glob::GLOB_BRACE); + $result = Glob::glob($globPattern, Glob::GLOB_BRACE); return is_array($result) ? $result : []; } diff --git a/lib/internal/Magento/Framework/Filesystem/Glob.php b/lib/internal/Magento/Framework/Filesystem/Glob.php new file mode 100644 index 0000000000000..eda65c158b4ad --- /dev/null +++ b/lib/internal/Magento/Framework/Filesystem/Glob.php @@ -0,0 +1,33 @@ + Date: Thu, 3 Mar 2016 19:38:31 +0200 Subject: [PATCH 05/30] MAGETWO-50076: [GitHub] Fix support for GLOB_BRACE on non-GNU Linux systems #3490 - fixed docblock - adjusted code formatting --- .../Magento/Mtf/Util/Generate/Factory/AbstractFactory.php | 5 ++--- lib/internal/Magento/Framework/App/Utility/Files.php | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Generate/Factory/AbstractFactory.php b/dev/tests/functional/lib/Magento/Mtf/Util/Generate/Factory/AbstractFactory.php index b0844503044ef..6cb159e9c970c 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Generate/Factory/AbstractFactory.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Generate/Factory/AbstractFactory.php @@ -26,11 +26,10 @@ abstract class AbstractFactory protected $_checkList = []; - /** - * @return mixed - */ /** * Generate Blocks + * + * @return void */ public function launch() { diff --git a/lib/internal/Magento/Framework/App/Utility/Files.php b/lib/internal/Magento/Framework/App/Utility/Files.php index ede7c32c5cffa..8334f8e8dde9e 100644 --- a/lib/internal/Magento/Framework/App/Utility/Files.php +++ b/lib/internal/Magento/Framework/App/Utility/Files.php @@ -951,10 +951,10 @@ protected function _parseModuleStatic($file) { foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $modulePath) { if (preg_match( - '/^' . preg_quote("{$modulePath}/", '/') . 'view\/([a-z]+)\/web\/(.+)$/i', - $file, - $matches - ) === 1 + '/^' . preg_quote("{$modulePath}/", '/') . 'view\/([a-z]+)\/web\/(.+)$/i', + $file, + $matches + ) === 1 ) { list(, $area, $filePath) = $matches; return [$area, '', '', $moduleName, $filePath, $file]; From 56f5c2ee4d0fe14334333b7c6321ce9049553125 Mon Sep 17 00:00:00 2001 From: Ihor Sytnykov Date: Thu, 14 Apr 2016 19:36:46 +0300 Subject: [PATCH 06/30] MDVA-260: GLOB_BRACE in Magento 2.0.4 --- lib/internal/Magento/Framework/Filesystem/Glob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filesystem/Glob.php b/lib/internal/Magento/Framework/Filesystem/Glob.php index eda65c158b4ad..f5a4fbeed0770 100644 --- a/lib/internal/Magento/Framework/Filesystem/Glob.php +++ b/lib/internal/Magento/Framework/Filesystem/Glob.php @@ -1,6 +1,6 @@ Date: Wed, 16 Mar 2016 13:26:43 -0500 Subject: [PATCH 07/30] MAGETWO-49212: [GITHUB] Magento\Sales\Model\OrderRepository::getList() is incomplete #3018 - added sort to the search logic --- app/code/Magento/Sales/Model/OrderRepository.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/OrderRepository.php b/app/code/Magento/Sales/Model/OrderRepository.php index 5ef75598b2f96..a1b309498f41c 100644 --- a/app/code/Magento/Sales/Model/OrderRepository.php +++ b/app/code/Magento/Sales/Model/OrderRepository.php @@ -15,6 +15,7 @@ use Magento\Sales\Api\Data\ShippingAssignmentInterface; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\InputException; +use Magento\Framework\Api\SortOrder; /** * Repository class for @see OrderInterface @@ -96,7 +97,6 @@ public function get($id) */ public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) { - //@TODO: fix search logic /** @var \Magento\Sales\Api\Data\OrderSearchResultInterface $searchResult */ $searchResult = $this->searchResultFactory->create(); foreach ($searchCriteria->getFilterGroups() as $filterGroup) { @@ -105,6 +105,20 @@ public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } + + $sortOrders = $searchCriteria->getSortOrders(); + if ($sortOrders === null) { + $sortOrders = []; + } + /** @var \Magento\Framework\Api\SortOrder $sortOrder */ + foreach ($sortOrders as $sortOrder) { + $field = $sortOrder->getField(); + $searchResult->addOrder( + $field, + ($sortOrder->getDirection() == SortOrder::SORT_ASC) ? 'ASC' : 'DESC' + ); + } + $searchResult->setCurPage($searchCriteria->getCurrentPage()); $searchResult->setPageSize($searchCriteria->getPageSize()); foreach ($searchResult->getItems() as $order) { From 8c99643a2e27367e605d21a029a26e05e78a2c4f Mon Sep 17 00:00:00 2001 From: "Partica, Cristian" Date: Wed, 16 Mar 2016 15:59:45 -0500 Subject: [PATCH 08/30] MAGETWO-49212: [GITHUB] Magento\Sales\Model\OrderRepository::getList() is incomplete #3018 - fixing OR logic when using filter_groups and multiple filters --- .../Magento/Sales/Model/OrderRepository.php | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/Model/OrderRepository.php b/app/code/Magento/Sales/Model/OrderRepository.php index a1b309498f41c..d57a8b8e92966 100644 --- a/app/code/Magento/Sales/Model/OrderRepository.php +++ b/app/code/Magento/Sales/Model/OrderRepository.php @@ -100,10 +100,7 @@ public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) /** @var \Magento\Sales\Api\Data\OrderSearchResultInterface $searchResult */ $searchResult = $this->searchResultFactory->create(); foreach ($searchCriteria->getFilterGroups() as $filterGroup) { - foreach ($filterGroup->getFilters() as $filter) { - $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; - $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); - } + $this->addFilterGroupToCollection($filterGroup, $searchResult); } $sortOrders = $searchCriteria->getSortOrders(); @@ -216,4 +213,28 @@ private function getShippingAssignmentBuilderDependency() } return $this->shippingAssignmentBuilder; } + + /** + * Helper function that adds a FilterGroup to the collection. + * + * @param \Magento\Framework\Api\Search\FilterGroup $filterGroup + * @param \Magento\Sales\Api\Data\OrderSearchResultInterface $searchResult + * @return void + * @throws \Magento\Framework\Exception\InputException + */ + protected function addFilterGroupToCollection( + \Magento\Framework\Api\Search\FilterGroup $filterGroup, + \Magento\Sales\Api\Data\OrderSearchResultInterface $searchResult + ) { + $fields = []; + $conditions = []; + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $conditions[] = [$condition => $filter->getValue()]; + $fields[] = $filter->getField(); + } + if ($fields) { + $searchResult->addFieldToFilter($fields, $conditions); + } + } } From f10d80267b2554e1ffc8b9276cce3b4d3c97399c Mon Sep 17 00:00:00 2001 From: "Partica, Cristian" Date: Wed, 16 Mar 2016 17:39:07 -0500 Subject: [PATCH 09/30] MAGETWO-49212: [GITHUB] Magento\Sales\Model\OrderRepository::getList() is incomplete #3018 - adding unit a test for the new logic, this repository wasn't covered by unit tests --- .../Test/Unit/Model/OrderRepositoryTest.php | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 app/code/Magento/Sales/Test/Unit/Model/OrderRepositoryTest.php diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/OrderRepositoryTest.php new file mode 100644 index 0000000000000..e4f52bb64f75e --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/OrderRepositoryTest.php @@ -0,0 +1,111 @@ +objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $className = 'Magento\Sales\Model\ResourceModel\Metadata'; + $this->metadata = $this->getMock($className, [], [], '', false); + + $className = 'Magento\Sales\Api\Data\OrderSearchResultInterfaceFactory'; + $this->searchResultFactory = $this->getMock($className, ['create'], [], '', false); + + $this->model = $this->objectManager->getObject( + '\Magento\Sales\Model\OrderRepository', + [ + 'metadata' => $this->metadata, + 'searchResultFactory' => $this->searchResultFactory, + ] + ); + } + + /** + * TODO: Cover with unit tests the other methods in the repository + * test GetList + */ + public function testGetList() + { + $fieldName = 'field'; + $searchCriteriaMock = $this->getMock('Magento\Framework\Api\SearchCriteria', [], [], '', false); + + $collectionMock = $this->getMock('Magento\Sales\Model\ResourceModel\Order\Collection', [], [], '', false); + + $filterGroupMock = $this->getMock('\Magento\Framework\Api\Search\FilterGroup', [], [], '', false); + $filterGroupFilterMock = $this->getMock('\Magento\Framework\Api\Filter', [], [], '', false); + $sortOrderMock = $this->getMock('\Magento\Framework\Api\SortOrder', [], [], '', false); + $itemsMock = $this->getMock('Magento\Sales\Model\Order', [], [], '', false); + + + $extensionAttributes = $this->getMock('\Magento\Sales\Api\Data\OrderExtension', [], [], '', false); + $shippingAssignmentBuilder = $this->getMock( + '\Magento\Sales\Model\Order\ShippingAssignmentBuilder', + [], + [], + '', + false + ); + + $itemsMock->expects($this->once())->method('getExtensionAttributes')->willReturn($extensionAttributes); + $extensionAttributes->expects($this->once()) + ->method('getShippingAssignments') + ->willReturn($shippingAssignmentBuilder); + + $this->searchResultFactory->expects($this->once())->method('create')->willReturn($collectionMock); + + $searchCriteriaMock->expects($this->once())->method('getFilterGroups')->willReturn([$filterGroupMock]); + $filterGroupMock->expects($this->once())->method('getFilters')->willReturn([$filterGroupFilterMock]); + $filterGroupFilterMock->expects($this->exactly(2))->method('getConditionType')->willReturn('eq'); + $filterGroupFilterMock->expects($this->atLeastOnce())->method('getField')->willReturn($fieldName); + $filterGroupFilterMock->expects($this->once())->method('getValue')->willReturn('value'); + $sortOrderMock->expects($this->once())->method('getDirection'); + $searchCriteriaMock->expects($this->once())->method('getSortOrders')->willReturn([$sortOrderMock]); + $sortOrderMock->expects($this->atLeastOnce())->method('getField')->willReturn($fieldName); + $collectionMock->expects($this->once())->method('addFieldToFilter') + ->willReturn(SortOrder::SORT_ASC); + $collectionMock->expects($this->once())->method('addOrder')->with($fieldName, 'DESC'); + $searchCriteriaMock->expects($this->once())->method('getCurrentPage')->willReturn(4); + $collectionMock->expects($this->once())->method('setCurPage')->with(4); + $searchCriteriaMock->expects($this->once())->method('getPageSize')->willReturn(42); + $collectionMock->expects($this->once())->method('setPageSize')->with(42); + $collectionMock->expects($this->once())->method('getItems')->willReturn([$itemsMock]); + + $this->assertEquals($collectionMock, $this->model->getList($searchCriteriaMock)); + } +} From 321f5f875eb1da95f089a0d18fd8629403beec65 Mon Sep 17 00:00:00 2001 From: "Partica, Cristian" Date: Thu, 17 Mar 2016 10:44:30 -0500 Subject: [PATCH 10/30] MAGETWO-49212: [GITHUB] Magento\Sales\Model\OrderRepository::getList() is incomplete #3018 - fixing a static failiure & unit test exception --- .../Sales/Test/Unit/Model/OrderRepositoryTest.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/OrderRepositoryTest.php index e4f52bb64f75e..90b11f6e7fd2b 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/OrderRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/OrderRepositoryTest.php @@ -19,6 +19,7 @@ class OrderRepositoryTest extends \PHPUnit_Framework_TestCase * @var \Magento\Sales\Model\OrderRepository */ protected $model; + /** * @var Metadata|\PHPUnit_Framework_MockObject_MockObject */ @@ -72,8 +73,13 @@ public function testGetList() $sortOrderMock = $this->getMock('\Magento\Framework\Api\SortOrder', [], [], '', false); $itemsMock = $this->getMock('Magento\Sales\Model\Order', [], [], '', false); - - $extensionAttributes = $this->getMock('\Magento\Sales\Api\Data\OrderExtension', [], [], '', false); + $extensionAttributes = $this->getMock( + '\Magento\Sales\Api\Data\OrderExtension', + ['getShippingAssignments'], + [], + '', + false + ); $shippingAssignmentBuilder = $this->getMock( '\Magento\Sales\Model\Order\ShippingAssignmentBuilder', [], @@ -83,7 +89,7 @@ public function testGetList() ); $itemsMock->expects($this->once())->method('getExtensionAttributes')->willReturn($extensionAttributes); - $extensionAttributes->expects($this->once()) + $extensionAttributes->expects($this->any()) ->method('getShippingAssignments') ->willReturn($shippingAssignmentBuilder); From a42a3febfd4118d139a3e0e59432d00ee8e02478 Mon Sep 17 00:00:00 2001 From: Anna Bukatar Date: Wed, 27 Apr 2016 17:43:56 +0300 Subject: [PATCH 11/30] MDVA-158: URL searchCriteria Logical OR - Added fix from MAGETWO-49212 --- app/code/Magento/Sales/Model/OrderRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/OrderRepository.php b/app/code/Magento/Sales/Model/OrderRepository.php index d57a8b8e92966..2f3ab181e6458 100644 --- a/app/code/Magento/Sales/Model/OrderRepository.php +++ b/app/code/Magento/Sales/Model/OrderRepository.php @@ -115,7 +115,7 @@ public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) ($sortOrder->getDirection() == SortOrder::SORT_ASC) ? 'ASC' : 'DESC' ); } - + $searchResult->setSearchCriteria($searchCriteria); $searchResult->setCurPage($searchCriteria->getCurrentPage()); $searchResult->setPageSize($searchCriteria->getPageSize()); foreach ($searchResult->getItems() as $order) { From 9fc059bc5b5432cadfd2f1cfa3cc2516e607e068 Mon Sep 17 00:00:00 2001 From: Ihor Sytnykov Date: Tue, 17 May 2016 21:27:08 +0300 Subject: [PATCH 12/30] =?UTF-8?q?MDVA-275:=20Emails=20from=20admin=20being?= =?UTF-8?q?=20sent=20out=20using=20default=20config=E2=80=99s=20email,=20n?= =?UTF-8?q?ot=20the=20specific=20store=20email?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/code/Magento/Checkout/Helper/Data.php | 2 ++ .../Customer/Model/AccountManagement.php | 1 + app/code/Magento/Customer/Model/Customer.php | 2 ++ .../Magento/Newsletter/Model/Subscriber.php | 15 ++++++++++++--- app/code/Magento/ProductAlert/Model/Email.php | 2 ++ .../Magento/Wishlist/Controller/Index/Send.php | 5 ++++- .../Mail/Template/TransportBuilder.php | 18 +++++++++++++++++- 7 files changed, 40 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Checkout/Helper/Data.php b/app/code/Magento/Checkout/Helper/Data.php index 2073ffe87d4d6..25d85dd4ee0cd 100644 --- a/app/code/Magento/Checkout/Helper/Data.php +++ b/app/code/Magento/Checkout/Helper/Data.php @@ -304,6 +304,8 @@ public function sendPaymentFailedEmail($checkout, $message, $checkoutType = 'one 'items' => nl2br($items), 'total' => $total, ] + )->setScopeId( + $checkout->getStoreId() )->setFrom( $this->scopeConfig->getValue( 'checkout/payment_failed/identity', diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index ee1201fab1c3e..07adf7b25f4cc 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -920,6 +920,7 @@ protected function sendEmailTemplate($customer, $template, $sender, $templatePar $transport = $this->transportBuilder->setTemplateIdentifier($templateId) ->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId]) ->setTemplateVars($templateParams) + ->setScopeId($storeId) ->setFrom($this->scopeConfig->getValue($sender, ScopeInterface::SCOPE_STORE, $storeId)) ->addTo($customer->getEmail(), $this->customerViewHelper->getCustomerName($customer)) ->getTransport(); diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php index 36e848729cd77..d46fc6dcdff20 100644 --- a/app/code/Magento/Customer/Model/Customer.php +++ b/app/code/Magento/Customer/Model/Customer.php @@ -828,6 +828,8 @@ protected function _sendEmailTemplate($template, $sender, $templateParams = [], ['area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'store' => $storeId] )->setTemplateVars( $templateParams + )->setScopeId( + $storeId )->setFrom( $this->_scopeConfig->getValue($sender, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $storeId) )->addTo( diff --git a/app/code/Magento/Newsletter/Model/Subscriber.php b/app/code/Magento/Newsletter/Model/Subscriber.php index 68b52264a3f6d..a208274a2cc8d 100644 --- a/app/code/Magento/Newsletter/Model/Subscriber.php +++ b/app/code/Magento/Newsletter/Model/Subscriber.php @@ -654,6 +654,7 @@ public function sendConfirmationRequestEmail() $this->inlineTranslation->suspend(); + $storeId = $this->_storeManager->getStore()->getId(); $this->_transportBuilder->setTemplateIdentifier( $this->_scopeConfig->getValue( self::XML_PATH_CONFIRM_EMAIL_TEMPLATE, @@ -662,10 +663,12 @@ public function sendConfirmationRequestEmail() )->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, - 'store' => $this->_storeManager->getStore()->getId(), + 'store' => $storeId, ] )->setTemplateVars( ['subscriber' => $this, 'store' => $this->_storeManager->getStore()] + )->setScopeId( + $storeId )->setFrom( $this->_scopeConfig->getValue( self::XML_PATH_CONFIRM_EMAIL_IDENTITY, @@ -707,6 +710,7 @@ public function sendConfirmationSuccessEmail() $this->inlineTranslation->suspend(); + $storeId = $this->_storeManager->getStore()->getId(); $this->_transportBuilder->setTemplateIdentifier( $this->_scopeConfig->getValue( self::XML_PATH_SUCCESS_EMAIL_TEMPLATE, @@ -715,10 +719,12 @@ public function sendConfirmationSuccessEmail() )->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, - 'store' => $this->_storeManager->getStore()->getId(), + 'store' => $storeId, ] )->setTemplateVars( ['subscriber' => $this] + )->setScopeId( + $storeId )->setFrom( $this->_scopeConfig->getValue( self::XML_PATH_SUCCESS_EMAIL_IDENTITY, @@ -759,6 +765,7 @@ public function sendUnsubscriptionEmail() $this->inlineTranslation->suspend(); + $storeId = $this->_storeManager->getStore()->getId(); $this->_transportBuilder->setTemplateIdentifier( $this->_scopeConfig->getValue( self::XML_PATH_UNSUBSCRIBE_EMAIL_TEMPLATE, @@ -767,10 +774,12 @@ public function sendUnsubscriptionEmail() )->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, - 'store' => $this->_storeManager->getStore()->getId(), + 'store' => $storeId, ] )->setTemplateVars( ['subscriber' => $this] + )->setScopeId( + $storeId )->setFrom( $this->_scopeConfig->getValue( self::XML_PATH_UNSUBSCRIBE_EMAIL_IDENTITY, diff --git a/app/code/Magento/ProductAlert/Model/Email.php b/app/code/Magento/ProductAlert/Model/Email.php index 1c70d7ff4a8e1..1eb884e1d82b2 100644 --- a/app/code/Magento/ProductAlert/Model/Email.php +++ b/app/code/Magento/ProductAlert/Model/Email.php @@ -374,6 +374,8 @@ public function send() 'customerName' => $this->_customerHelper->getCustomerName($this->_customer), 'alertGrid' => $alertGrid, ] + )->setScopeId( + $storeId )->setFrom( $this->_scopeConfig->getValue( self::XML_PATH_EMAIL_IDENTITY, diff --git a/app/code/Magento/Wishlist/Controller/Index/Send.php b/app/code/Magento/Wishlist/Controller/Index/Send.php index f0cf6464c257b..d286c4cccd43f 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Send.php +++ b/app/code/Magento/Wishlist/Controller/Index/Send.php @@ -186,6 +186,7 @@ public function execute() try { foreach ($emails as $email) { + $storeId = $this->storeManager->getStore()->getStoreId(); $transport = $this->_transportBuilder->setTemplateIdentifier( $this->scopeConfig->getValue( 'wishlist/email/email_template', @@ -194,7 +195,7 @@ public function execute() )->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, - 'store' => $this->storeManager->getStore()->getStoreId(), + 'store' => $storeId, ] )->setTemplateVars( [ @@ -206,6 +207,8 @@ public function execute() 'message' => $message, 'store' => $this->storeManager->getStore(), ] + )->setScopeId( + $storeId )->setFrom( $this->scopeConfig->getValue( 'wishlist/email/email_identity', diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 245597e794bb0..a2ceb5dac4a7c 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -84,6 +84,9 @@ class TransportBuilder */ protected $mailTransportFactory; + /** @var int|null */ + private $scopeId; + /** * @param FactoryInterface $templateFactory * @param MessageInterface $message @@ -156,6 +159,18 @@ public function setReplyTo($email, $name = null) return $this; } + /** + * Set scope + * + * @param int $scopeId + * @return $this + */ + public function setScopeId($scopeId) + { + $this->scopeId = $scopeId; + return $this; + } + /** * Set mail from address * @@ -164,7 +179,7 @@ public function setReplyTo($email, $name = null) */ public function setFrom($from) { - $result = $this->_senderResolver->resolve($from); + $result = $this->_senderResolver->resolve($from, $this->scopeId); $this->message->setFrom($result['email'], $result['name']); return $this; } @@ -242,6 +257,7 @@ protected function reset() $this->templateIdentifier = null; $this->templateVars = null; $this->templateOptions = null; + $this->scopeId = null; return $this; } From 3e3f35eb2ad9f61cb55cde43136225b634f790b9 Mon Sep 17 00:00:00 2001 From: Ihor Sytnykov Date: Tue, 17 May 2016 22:14:59 +0300 Subject: [PATCH 13/30] =?UTF-8?q?MDVA-275:=20Emails=20from=20admin=20being?= =?UTF-8?q?=20sent=20out=20using=20default=20config=E2=80=99s=20email,=20n?= =?UTF-8?q?ot=20the=20specific=20store=20email?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Checkout/Test/Unit/Helper/DataTest.php | 10 ++++++++++ .../Test/Unit/Model/AccountManagementTest.php | 16 ++++++++++++++++ .../Customer/Test/Unit/Model/CustomerTest.php | 1 + .../Test/Unit/Controller/Index/SendTest.php | 4 ++++ 4 files changed, 31 insertions(+) diff --git a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php index 9128419543e1c..96d6ac51ca15a 100644 --- a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php @@ -166,6 +166,16 @@ public function testSendPaymentFailedEmail() $this->returnSelf() ); + $this->_transportBuilder->expects( + $this->once() + )->method( + 'setScopeId' + )->with( + 8 + )->will( + $this->returnSelf() + ); + $this->_transportBuilder->expects( $this->once() )->method( diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 43e6973d9fd5c..9163573d121c3 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -650,6 +650,10 @@ public function testCreateAccountWithoutPassword() $this->transportBuilder->expects($this->once()) ->method('setTemplateVars') ->willReturnSelf(); + $this->transportBuilder->expects($this->once()) + ->method('setScopeId') + ->with($defaultStoreId) + ->willReturnSelf(); $this->transportBuilder->expects($this->once()) ->method('setFrom') ->with($sender) @@ -799,6 +803,10 @@ function ($string) { $this->transportBuilder->expects($this->once()) ->method('setTemplateVars') ->willReturnSelf(); + $this->transportBuilder->expects($this->once()) + ->method('setScopeId') + ->with($defaultStoreId) + ->willReturnSelf(); $this->transportBuilder->expects($this->once()) ->method('setFrom') ->with($sender) @@ -901,6 +909,10 @@ public function testSendPasswordReminderEmail() ->method('setTemplateVars') ->with(['customer' => $this->customerSecure, 'store' => $this->store]) ->willReturnSelf(); + $this->transportBuilder->expects($this->once()) + ->method('setScopeId') + ->with($customerStoreId) + ->willReturnSelf(); $this->transportBuilder->expects($this->once()) ->method('setFrom') ->with($sender) @@ -1031,6 +1043,10 @@ protected function prepareEmailSend($email, $templateIdentifier, $sender, $store ->method('setTemplateVars') ->with(['customer' => $this->customerSecure, 'store' => $this->store]) ->willReturnSelf(); + $this->transportBuilder->expects($this->any()) + ->method('setScopeId') + ->with($storeId) + ->willReturnSelf(); $this->transportBuilder->expects($this->any()) ->method('setFrom') ->with($sender) diff --git a/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php b/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php index 6631703b2ada7..1096868dafab6 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php @@ -215,6 +215,7 @@ public function testSendNewAccountEmailWithoutStoreId() 'setTemplateIdentifier', 'setTemplateOptions', 'setTemplateVars', + 'setScopeId', 'setFrom', 'addTo', ]; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php index 152a5ffe48ecd..1933611b75d68 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php @@ -662,6 +662,10 @@ public function testExecute() 'store' => $this->store, ]) ->willReturnSelf(); + $this->transportBuilder->expects($this->once()) + ->method('setScopeId') + ->with($storeId) + ->willReturnSelf(); $this->transportBuilder->expects($this->once()) ->method('setFrom') ->with($from) From 3cfa3bca49c70b07feb0074a2e74a161865d24d1 Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Mon, 16 May 2016 16:05:13 +0300 Subject: [PATCH 14/30] MAGETWO-46014: delayed error messages --- .../Theme/Controller/Result/MessagePlugin.php | 134 ++++++ .../Controller/Result/MessagePluginTest.php | 419 ++++++++++++++++++ app/code/Magento/Theme/etc/frontend/di.xml | 3 + .../view/frontend/templates/messages.phtml | 8 + .../view/frontend/web/js/view/messages.js | 12 +- 5 files changed, 574 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Theme/Controller/Result/MessagePlugin.php create mode 100644 app/code/Magento/Theme/Test/Unit/Controller/Result/MessagePluginTest.php diff --git a/app/code/Magento/Theme/Controller/Result/MessagePlugin.php b/app/code/Magento/Theme/Controller/Result/MessagePlugin.php new file mode 100644 index 0000000000000..b95a80e5be714 --- /dev/null +++ b/app/code/Magento/Theme/Controller/Result/MessagePlugin.php @@ -0,0 +1,134 @@ +cookieManager = $cookieManager; + $this->cookieMetadataFactory = $cookieMetadataFactory; + $this->messageManager = $messageManager; + $this->jsonHelper = $jsonHelper; + $this->interpretationStrategy = $interpretationStrategy; + } + + /** + * @param ResultInterface $subject + * @param ResultInterface $result + * @return ResultInterface + */ + public function afterRenderResult( + ResultInterface $subject, + ResultInterface $result + ) { + if (!($subject instanceof Json)) { + $publicCookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata(); + $publicCookieMetadata->setDurationOneYear(); + $publicCookieMetadata->setPath('/'); + $publicCookieMetadata->setHttpOnly(false); + $this->cookieManager->setPublicCookie( + self::MESSAGES_COOKIES_NAME, + $this->jsonHelper->jsonEncode($this->getMessages()), + $publicCookieMetadata + ); + } + + return $result; + } + + /** + * Return messages array and clean message manager messages + * + * @return array + */ + protected function getMessages() + { + $messages = $this->getCookiesMessages(); + /** @var MessageInterface $message */ + foreach ($this->messageManager->getMessages(true)->getItems() as $message) { + $messages []= [ + 'type' => $message->getType(), + 'text' => $this->interpretationStrategy->interpret($message), + ]; + } + return $messages; + } + + /** + * Return messages stored in cookies + * + * @return array + */ + protected function getCookiesMessages() + { + try { + $messages = $this->jsonHelper->jsonDecode( + $this->cookieManager->getCookie(self::MESSAGES_COOKIES_NAME, $this->jsonHelper->jsonEncode([])) + ); + if (!is_array($messages)) { + $messages = []; + } + } catch (\Zend_Json_Exception $e) { + $messages = []; + } + return $messages; + } +} diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/MessagePluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/MessagePluginTest.php new file mode 100644 index 0000000000000..c7e76e9993d39 --- /dev/null +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/MessagePluginTest.php @@ -0,0 +1,419 @@ +cookieManagerMock = $this->getMockBuilder(CookieManagerInterface::class) + ->getMockForAbstractClass(); + $this->cookieMetadataFactoryMock = $this->getMockBuilder(CookieMetadataFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->managerMock = $this->getMockBuilder(ManagerInterface::class) + ->getMockForAbstractClass(); + $this->interpretationStrategyMock = $this->getMockBuilder(InterpretationStrategyInterface::class) + ->getMockForAbstractClass(); + $this->dataMock = $this->getMockBuilder(Data::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new MessagePlugin( + $this->cookieManagerMock, + $this->cookieMetadataFactoryMock, + $this->managerMock, + $this->interpretationStrategyMock, + $this->dataMock + ); + } + + public function testAfterRenderResultJson() + { + /** @var Json|\PHPUnit_Framework_MockObject_MockObject $resultMock */ + $resultMock = $this->getMockBuilder(Json::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->cookieManagerMock->expects($this->never()) + ->method('setPublicCookie'); + + $this->assertEquals($resultMock, $this->model->afterRenderResult($resultMock, $resultMock)); + } + + public function testAfterRenderResult() + { + + $existingMessages = [ + [ + 'type' => 'message0type', + 'text' => 'message0text', + ], + ]; + $messageType = 'message1type'; + $messageText = 'message1text'; + $messages = [ + [ + 'type' => $messageType, + 'text' => $messageText, + ], + ]; + $messages = array_merge($existingMessages, $messages); + + /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $resultMock */ + $resultMock = $this->getMockBuilder(Redirect::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var PublicCookieMetadata|\PHPUnit_Framework_MockObject_MockObject $cookieMetadataMock */ + $cookieMetadataMock = $this->getMockBuilder(PublicCookieMetadata::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->cookieMetadataFactoryMock->expects($this->once()) + ->method('createPublicCookieMetadata') + ->willReturn($cookieMetadataMock); + + $this->cookieManagerMock->expects($this->once()) + ->method('setPublicCookie') + ->with( + MessagePlugin::MESSAGES_COOKIES_NAME, + \Zend_Json::encode($messages), + $cookieMetadataMock + ); + $this->cookieManagerMock->expects($this->once()) + ->method('getCookie') + ->with( + MessagePlugin::MESSAGES_COOKIES_NAME, + \Zend_Json::encode([]) + ) + ->willReturn(\Zend_Json::encode($existingMessages)); + + $this->dataMock->expects($this->any()) + ->method('jsonDecode') + ->willReturnCallback( + function ($data) + { + return \Zend_Json::decode($data); + } + ); + $this->dataMock->expects($this->any()) + ->method('jsonEncode') + ->willReturnCallback( + function ($data) + { + return \Zend_Json::encode($data); + } + ); + + /** @var MessageInterface|\PHPUnit_Framework_MockObject_MockObject $messageMock */ + $messageMock = $this->getMockBuilder(MessageInterface::class) + ->getMock(); + $messageMock->expects($this->once()) + ->method('getType') + ->willReturn($messageType); + + $this->interpretationStrategyMock->expects($this->once()) + ->method('interpret') + ->with($messageMock) + ->willReturn($messageText); + + /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + $collectionMock = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->once()) + ->method('getItems') + ->willReturn([$messageMock]); + + $this->managerMock->expects($this->once()) + ->method('getMessages') + ->with(true, null) + ->willReturn($collectionMock); + + $this->assertEquals($resultMock, $this->model->afterRenderResult($resultMock, $resultMock)); + } + + public function testAfterRenderResultWithoutExisting() + { + $messageType = 'message1type'; + $messageText = 'message1text'; + $messages = [ + [ + 'type' => $messageType, + 'text' => $messageText, + ], + ]; + + /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $resultMock */ + $resultMock = $this->getMockBuilder(Redirect::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var PublicCookieMetadata|\PHPUnit_Framework_MockObject_MockObject $cookieMetadataMock */ + $cookieMetadataMock = $this->getMockBuilder(PublicCookieMetadata::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->cookieMetadataFactoryMock->expects($this->once()) + ->method('createPublicCookieMetadata') + ->willReturn($cookieMetadataMock); + + $this->cookieManagerMock->expects($this->once()) + ->method('setPublicCookie') + ->with( + MessagePlugin::MESSAGES_COOKIES_NAME, + \Zend_Json::encode($messages), + $cookieMetadataMock + ); + $this->cookieManagerMock->expects($this->once()) + ->method('getCookie') + ->with( + MessagePlugin::MESSAGES_COOKIES_NAME, + \Zend_Json::encode([]) + ) + ->willReturn(\Zend_Json::encode([])); + + $this->dataMock->expects($this->any()) + ->method('jsonDecode') + ->willReturnCallback( + function ($data) + { + return \Zend_Json::decode($data); + } + ); + $this->dataMock->expects($this->any()) + ->method('jsonEncode') + ->willReturnCallback( + function ($data) + { + return \Zend_Json::encode($data); + } + ); + + /** @var MessageInterface|\PHPUnit_Framework_MockObject_MockObject $messageMock */ + $messageMock = $this->getMockBuilder(MessageInterface::class) + ->getMock(); + $messageMock->expects($this->once()) + ->method('getType') + ->willReturn($messageType); + + $this->interpretationStrategyMock->expects($this->once()) + ->method('interpret') + ->with($messageMock) + ->willReturn($messageText); + + /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + $collectionMock = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->once()) + ->method('getItems') + ->willReturn([$messageMock]); + + $this->managerMock->expects($this->once()) + ->method('getMessages') + ->with(true, null) + ->willReturn($collectionMock); + + $this->assertEquals($resultMock, $this->model->afterRenderResult($resultMock, $resultMock)); + } + + public function testAfterRenderResultWithWrongJson() + { + $messageType = 'message1type'; + $messageText = 'message1text'; + $messages = [ + [ + 'type' => $messageType, + 'text' => $messageText, + ], + ]; + + /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $resultMock */ + $resultMock = $this->getMockBuilder(Redirect::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var PublicCookieMetadata|\PHPUnit_Framework_MockObject_MockObject $cookieMetadataMock */ + $cookieMetadataMock = $this->getMockBuilder(PublicCookieMetadata::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->cookieMetadataFactoryMock->expects($this->once()) + ->method('createPublicCookieMetadata') + ->willReturn($cookieMetadataMock); + + $this->cookieManagerMock->expects($this->once()) + ->method('setPublicCookie') + ->with( + MessagePlugin::MESSAGES_COOKIES_NAME, + \Zend_Json::encode($messages), + $cookieMetadataMock + ); + $this->cookieManagerMock->expects($this->once()) + ->method('getCookie') + ->with( + MessagePlugin::MESSAGES_COOKIES_NAME, + \Zend_Json::encode([]) + ) + ->willReturn(\Zend_Json::encode([])); + + $this->dataMock->expects($this->any()) + ->method('jsonDecode') + ->willThrowException(new \Zend_Json_Exception); + $this->dataMock->expects($this->any()) + ->method('jsonEncode') + ->willReturnCallback( + function ($data) + { + return \Zend_Json::encode($data); + } + ); + + /** @var MessageInterface|\PHPUnit_Framework_MockObject_MockObject $messageMock */ + $messageMock = $this->getMockBuilder(MessageInterface::class) + ->getMock(); + $messageMock->expects($this->once()) + ->method('getType') + ->willReturn($messageType); + + $this->interpretationStrategyMock->expects($this->once()) + ->method('interpret') + ->with($messageMock) + ->willReturn($messageText); + + /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + $collectionMock = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->once()) + ->method('getItems') + ->willReturn([$messageMock]); + + $this->managerMock->expects($this->once()) + ->method('getMessages') + ->with(true, null) + ->willReturn($collectionMock); + + $this->assertEquals($resultMock, $this->model->afterRenderResult($resultMock, $resultMock)); + } + + public function testAfterRenderResultWithWrongArray() + { + $messageType = 'message1type'; + $messageText = 'message1text'; + $messages = [ + [ + 'type' => $messageType, + 'text' => $messageText, + ], + ]; + + /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $resultMock */ + $resultMock = $this->getMockBuilder(Redirect::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var PublicCookieMetadata|\PHPUnit_Framework_MockObject_MockObject $cookieMetadataMock */ + $cookieMetadataMock = $this->getMockBuilder(PublicCookieMetadata::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->cookieMetadataFactoryMock->expects($this->once()) + ->method('createPublicCookieMetadata') + ->willReturn($cookieMetadataMock); + + $this->cookieManagerMock->expects($this->once()) + ->method('setPublicCookie') + ->with( + MessagePlugin::MESSAGES_COOKIES_NAME, + \Zend_Json::encode($messages), + $cookieMetadataMock + ); + $this->cookieManagerMock->expects($this->once()) + ->method('getCookie') + ->with( + MessagePlugin::MESSAGES_COOKIES_NAME, + \Zend_Json::encode([]) + ) + ->willReturn(\Zend_Json::encode('string')); + + $this->dataMock->expects($this->any()) + ->method('jsonDecode') + ->willReturnCallback( + function ($data) + { + return \Zend_Json::decode($data); + } + ); + $this->dataMock->expects($this->any()) + ->method('jsonEncode') + ->willReturnCallback( + function ($data) + { + return \Zend_Json::encode($data); + } + ); + + /** @var MessageInterface|\PHPUnit_Framework_MockObject_MockObject $messageMock */ + $messageMock = $this->getMockBuilder(MessageInterface::class) + ->getMock(); + $messageMock->expects($this->once()) + ->method('getType') + ->willReturn($messageType); + + $this->interpretationStrategyMock->expects($this->once()) + ->method('interpret') + ->with($messageMock) + ->willReturn($messageText); + + /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + $collectionMock = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->once()) + ->method('getItems') + ->willReturn([$messageMock]); + + $this->managerMock->expects($this->once()) + ->method('getMessages') + ->with(true, null) + ->willReturn($collectionMock); + + $this->assertEquals($resultMock, $this->model->afterRenderResult($resultMock, $resultMock)); + } +} diff --git a/app/code/Magento/Theme/etc/frontend/di.xml b/app/code/Magento/Theme/etc/frontend/di.xml index a260164e4f598..85086d694f378 100644 --- a/app/code/Magento/Theme/etc/frontend/di.xml +++ b/app/code/Magento/Theme/etc/frontend/di.xml @@ -23,4 +23,7 @@ + + + diff --git a/app/code/Magento/Theme/view/frontend/templates/messages.phtml b/app/code/Magento/Theme/view/frontend/templates/messages.phtml index 595c4fa7d3d6e..2bd2357a27e1a 100644 --- a/app/code/Magento/Theme/view/frontend/templates/messages.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/messages.phtml @@ -5,6 +5,14 @@ */ ?>
+
+
+
+
+
', (string)$message->getText()); - } - $this->assertTrue($isProductNamePresent, 'Product name was not found in session messages'); + $product = $this->productRepository->get('product-with-xss'); + $this->dispatch('catalog/product_compare/remove/product/' . $product->getEntityId() . '?nocookie=1'); + + $this->assertSessionMessages( + $this->logicalNot($this->contains('')) + ); + $this->assertSessionMessages( + $this->contains('<script>alert("xss");</script>'), + MessageInterface::TYPE_SUCCESS + ); } protected function _prepareCompareListWithProductNameXss() @@ -171,7 +162,8 @@ protected function _prepareCompareListWithProductNameXss() $item = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( 'Magento\Catalog\Model\Product\Compare\Item' ); - $item->setVisitorId($visitor->getId())->setProductId(1)->save(); + $firstProductEntityId = $this->productRepository->get('product-with-xss')->getEntityId(); + $item->setVisitorId($visitor->getId())->setProductId($firstProductEntityId)->save(); \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( 'Magento\Customer\Model\Visitor' )->load( @@ -211,13 +203,15 @@ protected function _requireVisitorWithTwoProducts() $item = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( 'Magento\Catalog\Model\Product\Compare\Item' ); - $item->setVisitorId($visitor->getId())->setProductId(1)->save(); + $firstProductEntityId = $this->productRepository->get('simple_product_1')->getEntityId(); + $secondProductEntityId = $this->productRepository->get('simple_product_2')->getEntityId(); + $item->setVisitorId($visitor->getId())->setProductId($firstProductEntityId)->save(); /** @var $item \Magento\Catalog\Model\Product\Compare\Item */ $item = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( 'Magento\Catalog\Model\Product\Compare\Item' ); - $item->setVisitorId($visitor->getId())->setProductId(2)->save(); + $item->setVisitorId($visitor->getId())->setProductId($secondProductEntityId)->save(); \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( 'Magento\Customer\Model\Visitor' @@ -225,7 +219,7 @@ protected function _requireVisitorWithTwoProducts() $visitor->getId() ); - $this->_assertCompareListEquals([1, 2]); + $this->_assertCompareListEquals([$firstProductEntityId, $secondProductEntityId]); } protected function _requireCustomerWithTwoProducts() @@ -262,25 +256,28 @@ protected function _requireCustomerWithTwoProducts() ->setLastVisitAt((new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)) ->save(); + $firstProductEntityId = $this->productRepository->get('simple_product_1')->getEntityId(); + $secondProductEntityId = $this->productRepository->get('simple_product_2')->getEntityId(); + /** @var $item \Magento\Catalog\Model\Product\Compare\Item */ $item = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create('Magento\Catalog\Model\Product\Compare\Item'); $item->setVisitorId($visitor->getId()) ->setCustomerId(1) - ->setProductId(1) + ->setProductId($firstProductEntityId) ->save(); /** @var $item \Magento\Catalog\Model\Product\Compare\Item */ $item = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create('Magento\Catalog\Model\Product\Compare\Item'); $item->setVisitorId($visitor->getId()) - ->setProductId(2) + ->setProductId($secondProductEntityId) ->save(); \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Customer\Model\Visitor') ->load($visitor->getId()); - $this->_assertCompareListEquals([1, 2]); + $this->_assertCompareListEquals([$firstProductEntityId, $secondProductEntityId]); } /** From 5cad954938873846aa83d9e3c45b76f236c63717 Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Tue, 17 May 2016 17:04:44 +0300 Subject: [PATCH 17/30] MAGETWO-46014: delayed error messages --- .../Controller/Product/CompareTest.php | 24 ++++++++---- .../Magento/Wishlist/Controller/IndexTest.php | 39 +++++++++---------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php index 7307a119a197c..413a8941d3d43 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Product/CompareTest.php @@ -44,7 +44,10 @@ public function testAddAction() ) ); - $this->assertSessionMessages($this->contains('Simple Product 1 Name'), MessageInterface::TYPE_SUCCESS); + $this->assertSessionMessages( + $this->equalTo(['You added product Simple Product 1 Name to the comparison list.']), + MessageInterface::TYPE_SUCCESS + ); $this->assertRedirect(); @@ -68,7 +71,10 @@ public function testRemoveAction() $product = $this->productRepository->get('simple_product_2'); $this->dispatch('catalog/product_compare/remove/product/' . $product->getEntityId()); - $this->assertSessionMessages($this->contains('Simple Product 2 Name'), MessageInterface::TYPE_SUCCESS); + $this->assertSessionMessages( + $this->equalTo(['You removed product Simple Product 2 Name from the comparison list.']), + MessageInterface::TYPE_SUCCESS + ); $this->assertRedirect(); $restProduct = $this->productRepository->get('simple_product_1'); @@ -82,7 +88,10 @@ public function testRemoveActionWithSession() $this->dispatch('catalog/product_compare/remove/product/' . $product->getEntityId()); $secondProduct = $this->productRepository->get('simple_product_2'); - $this->assertSessionMessages($this->contains('Simple Product 1 Name'), MessageInterface::TYPE_SUCCESS); + $this->assertSessionMessages( + $this->equalTo(['You removed product Simple Product 1 Name from the comparison list.']), + MessageInterface::TYPE_SUCCESS + ); $this->assertRedirect(); @@ -122,7 +131,7 @@ public function testClearAction() $this->dispatch('catalog/product_compare/clear'); $this->assertSessionMessages( - $this->contains('You cleared the comparison list.'), + $this->equalTo(['You cleared the comparison list.']), MessageInterface::TYPE_SUCCESS ); @@ -141,10 +150,9 @@ public function testRemoveActionProductNameXss() $this->dispatch('catalog/product_compare/remove/product/' . $product->getEntityId() . '?nocookie=1'); $this->assertSessionMessages( - $this->logicalNot($this->contains('')) - ); - $this->assertSessionMessages( - $this->contains('<script>alert("xss");</script>'), + $this->equalTo( + ['You removed product <script>alert("xss");</script> from the comparison list.'] + ), MessageInterface::TYPE_SUCCESS ); } diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php index 527650f1b02dc..347f4999525b0 100644 --- a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php @@ -83,29 +83,26 @@ public function testItemColumnBlock() */ public function testAddActionProductNameXss() { - $this->dispatch('wishlist/index/add/product/1?nocookie=1'); - $messages = $this->_messages->getMessages()->getItems(); - $isProductNamePresent = false; + /** @var \Magento\Framework\Data\Form\FormKey $formKey */ + $formKey = $this->_objectManager->get('Magento\Framework\Data\Form\FormKey'); + $this->getRequest()->setPostValue([ + 'form_key' => $formKey->getFormKey(), + ]); - /** @var InterpretationStrategyInterface $interpretationStrategy */ - $interpretationStrategy = $this->_objectManager->create( - 'Magento\Framework\View\Element\Message\InterpretationStrategyInterface' + /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ + $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create('Magento\Catalog\Api\ProductRepositoryInterface'); + + $product = $productRepository->get('product-with-xss'); + + $this->dispatch('wishlist/index/add/product/' . $product->getId() . '?nocookie=1'); + + $this->assertSessionMessages( + $this->equalTo( + ['You removed product <script>alert("xss");</script> from the comparison list.'] + ), + \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS ); - foreach ($messages as $message) { - if ( - strpos( - $interpretationStrategy->interpret($message), - '<script>alert("xss");</script>' - ) !== false - ) { - $isProductNamePresent = true; - } - $this->assertNotContains( - '', - $interpretationStrategy->interpret($message) - ); - } - $this->assertTrue($isProductNamePresent, 'Product name was not found in session messages'); } /** From 402b6c894c7d48360cf3da20f8385c6cee40ded7 Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Tue, 17 May 2016 17:17:49 +0300 Subject: [PATCH 18/30] MAGETWO-46014: delayed error messages --- .../TestCase/AbstractController.php | 3 +- .../Test/TestCase/ControllerAbstractTest.php | 45 +++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php b/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php index fbf34e319e6eb..2712102ee4e01 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php +++ b/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php @@ -228,7 +228,8 @@ public function assertSessionMessages( * @param string|null $messageType * @return array */ - private function getCookieMessages($messageType = null) { + private function getCookieMessages($messageType = null) + { /** @var $cookieManager CookieManagerInterface */ $cookieManager = $this->_objectManager->get(CookieManagerInterface::class); try { diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php index ad396dd7a36ea..96e1878130e0c 100644 --- a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ namespace Magento\Test\TestCase; +use Magento\Framework\Stdlib\CookieManagerInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -15,11 +16,15 @@ class ControllerAbstractTest extends \Magento\TestFramework\TestCase\AbstractCon /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Message\Manager */ private $messageManager; + /** @var \PHPUnit_Framework_MockObject_MockObject | CookieManagerInterface */ + private $cookieManagerMock; + protected function setUp() { $testObjectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->messageManager = $this->getMock('\Magento\Framework\Message\Manager', [], [], '', false); + $this->cookieManagerMock = $this->getMock(CookieManagerInterface::class, [], [], '', false); $request = $testObjectManager->getObject('Magento\TestFramework\Request'); $response = $testObjectManager->getObject('Magento\TestFramework\Response'); $this->_objectManager = $this->getMock( @@ -37,6 +42,7 @@ protected function setUp() ['Magento\Framework\App\RequestInterface', $request], ['Magento\Framework\App\ResponseInterface', $response], ['Magento\Framework\Message\Manager', $this->messageManager], + [CookieManagerInterface::class, $this->cookieManagerMock], ] ) ); @@ -139,16 +145,20 @@ public function testAssertSessionMessagesSuccess(array $expectedMessages, $messa public function assertSessionMessagesDataProvider() { return [ - 'message waning type filtering' => [ - ['some_warning'], + 'message warning type filtering' => [ + ['some_warning', 'warning_cookie'], \Magento\Framework\Message\MessageInterface::TYPE_WARNING, ], 'message error type filtering' => [ - ['error_one', 'error_two'], + ['error_one', 'error_two', 'error_cookie'], \Magento\Framework\Message\MessageInterface::TYPE_ERROR, ], + 'message notice type filtering' => [ + ['some_notice', 'notice_cookie'], + \Magento\Framework\Message\MessageInterface::TYPE_NOTICE, + ], 'message success type filtering' => [ - ['success!'], + ['success!', 'success_cookie'], \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS, ], ]; @@ -166,6 +176,10 @@ public function testAssertSessionMessagesAll() 'error_two', 'some_notice', 'success!', + 'warning_cookie', + 'notice_cookie', + 'success_cookie', + 'error_cookie', ] ) ); @@ -192,5 +206,28 @@ private function addSessionMessages() ->addMessage(new \Magento\Framework\Message\Success('success!')); $this->messageManager->expects($this->any())->method('getMessages') ->will($this->returnValue($messagesCollection)); + + $cookieMessages = [ + [ + 'type' => 'warning', + 'text' => 'warning_cookie', + ], + [ + 'type' => 'notice', + 'text' => 'notice_cookie', + ], + [ + 'type' => 'success', + 'text' => 'success_cookie', + ], + [ + 'type' => 'error', + 'text' => 'error_cookie', + ], + ]; + + $this->cookieManagerMock->expects($this->any()) + ->method('getCookie') + ->willReturn(\Zend_Json::encode($cookieMessages)); } } From 5f019182a6428ed12b2618e6f087d525e41005e4 Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Tue, 17 May 2016 19:01:49 +0300 Subject: [PATCH 19/30] MAGETWO-46014: delayed error messages --- .../TestCase/AbstractController.php | 58 +++++++++++++++---- .../Test/TestCase/ControllerAbstractTest.php | 23 ++++++-- .../Magento/Wishlist/Controller/IndexTest.php | 7 ++- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php b/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php index 2712102ee4e01..622050dfc278a 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php +++ b/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php @@ -10,6 +10,7 @@ namespace Magento\TestFramework\TestCase; use Magento\Framework\Stdlib\CookieManagerInterface; +use Magento\Framework\View\Element\Message\InterpretationStrategyInterface; use Magento\Theme\Controller\Result\MessagePlugin; /** @@ -181,11 +182,11 @@ public function assertRedirect(\PHPUnit_Framework_Constraint $urlConstraint = nu } } - /** + /**ishlist/Controller/IndexTest * Assert that actual session messages meet expectations: * Usage examples: * $this->assertSessionMessages($this->isEmpty(), \Magento\Framework\Message\MessageInterface::TYPE_ERROR); - * $this->assertSessionMessages($this->equalTo(array('Entity has been saved.')), + * $this->assertSessionMessages($this->equalTo(['Entity has been saved.'], * \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS); * * @param \PHPUnit_Framework_Constraint $constraint Constraint to compare actual messages against @@ -199,6 +200,44 @@ public function assertSessionMessages( $messageManagerClass = 'Magento\Framework\Message\Manager' ) { $this->_assertSessionErrors = false; + + $messages = $this->getMessages($messageType, $messageManagerClass); + + $this->assertThat( + $messages, + $constraint, + 'Session messages do not meet expectations ' . var_export($messages, true) + ); + } + + /** + * Return all stored messages + * + * @param string|null $messageType + * @param string $messageManagerClass + * @return array + */ + protected function getMessages( + $messageType = null, + $messageManagerClass = 'Magento\Framework\Message\Manager' + ) { + return array_merge( + $this->getSessionMessages($messageType, $messageManagerClass), + $this->getCookieMessages($messageType) + ); + } + + /** + * Return messages stored in session + * + * @param string|null $messageType + * @param string $messageManagerClass + * @return array + */ + protected function getSessionMessages( + $messageType = null, + $messageManagerClass = 'Magento\Framework\Message\Manager' + ) { /** @var $messageManager \Magento\Framework\Message\ManagerInterface */ $messageManager = $this->_objectManager->get($messageManagerClass); /** @var $messages \Magento\Framework\Message\AbstractMessage[] */ @@ -208,18 +247,15 @@ public function assertSessionMessages( $messages = $messageManager->getMessages()->getItemsByType($messageType); } + /** @var $messageManager InterpretationStrategyInterface */ + $interpretationStrategy = $this->_objectManager->get(InterpretationStrategyInterface::class); + $actualMessages = []; foreach ($messages as $message) { - $actualMessages[] = $message->getText(); + $actualMessages[] = $interpretationStrategy->interpret($message); } - $actualMessages = array_merge($actualMessages, $this->getCookieMessages($messageType)); - - $this->assertThat( - $actualMessages, - $constraint, - 'Session messages do not meet expectations' . var_export($actualMessages, true) - ); + return $actualMessages; } /** @@ -228,7 +264,7 @@ public function assertSessionMessages( * @param string|null $messageType * @return array */ - private function getCookieMessages($messageType = null) + protected function getCookieMessages($messageType = null) { /** @var $cookieManager CookieManagerInterface */ $cookieManager = $this->_objectManager->get(CookieManagerInterface::class); diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php index 96e1878130e0c..794b1b0b21e77 100644 --- a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php @@ -4,7 +4,9 @@ * See COPYING.txt for license details. */ namespace Magento\Test\TestCase; +use Magento\Framework\Message\MessageInterface; use Magento\Framework\Stdlib\CookieManagerInterface; +use Magento\Framework\View\Element\Message\InterpretationStrategyInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -16,6 +18,9 @@ class ControllerAbstractTest extends \Magento\TestFramework\TestCase\AbstractCon /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Message\Manager */ private $messageManager; + /** @var \PHPUnit_Framework_MockObject_MockObject | InterpretationStrategyInterface */ + private $interpretationStrategyMock; + /** @var \PHPUnit_Framework_MockObject_MockObject | CookieManagerInterface */ private $cookieManagerMock; @@ -25,6 +30,15 @@ protected function setUp() $this->messageManager = $this->getMock('\Magento\Framework\Message\Manager', [], [], '', false); $this->cookieManagerMock = $this->getMock(CookieManagerInterface::class, [], [], '', false); + $this->interpretationStrategyMock = $this->getMock(InterpretationStrategyInterface::class, [], [], '', false); + $this->interpretationStrategyMock->expects($this->any()) + ->method('interpret') + ->willReturnCallback( + function (MessageInterface $message) { + return $message->getText(); + } + ); + $request = $testObjectManager->getObject('Magento\TestFramework\Request'); $response = $testObjectManager->getObject('Magento\TestFramework\Response'); $this->_objectManager = $this->getMock( @@ -43,6 +57,7 @@ protected function setUp() ['Magento\Framework\App\ResponseInterface', $response], ['Magento\Framework\Message\Manager', $this->messageManager], [CookieManagerInterface::class, $this->cookieManagerMock], + [InterpretationStrategyInterface::class, $this->interpretationStrategyMock], ] ) ); @@ -147,19 +162,19 @@ public function assertSessionMessagesDataProvider() return [ 'message warning type filtering' => [ ['some_warning', 'warning_cookie'], - \Magento\Framework\Message\MessageInterface::TYPE_WARNING, + MessageInterface::TYPE_WARNING, ], 'message error type filtering' => [ ['error_one', 'error_two', 'error_cookie'], - \Magento\Framework\Message\MessageInterface::TYPE_ERROR, + MessageInterface::TYPE_ERROR, ], 'message notice type filtering' => [ ['some_notice', 'notice_cookie'], - \Magento\Framework\Message\MessageInterface::TYPE_NOTICE, + MessageInterface::TYPE_NOTICE, ], 'message success type filtering' => [ ['success!', 'success_cookie'], - \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS, + MessageInterface::TYPE_SUCCESS, ], ]; } diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php index 347f4999525b0..e409a55c504b5 100644 --- a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php @@ -5,8 +5,6 @@ */ namespace Magento\Wishlist\Controller; -use Magento\Framework\View\Element\Message\InterpretationStrategyInterface; - class IndexTest extends \Magento\TestFramework\TestCase\AbstractController { /** @@ -99,7 +97,10 @@ public function testAddActionProductNameXss() $this->assertSessionMessages( $this->equalTo( - ['You removed product <script>alert("xss");</script> from the comparison list.'] + [ + "\n<script>alert("xss");</script> has been added to your Wish List. " + . 'Click here to continue shopping.', + ] ), \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS ); From 832fd9345334d2c78f1b4dde5d30609f7b653bfa Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Tue, 17 May 2016 19:17:46 +0300 Subject: [PATCH 20/30] MAGETWO-46014: delayed error messages --- .../testsuite/Magento/Test/TestCase/ControllerAbstractTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php index 794b1b0b21e77..b97d485845535 100644 --- a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/TestCase/ControllerAbstractTest.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ namespace Magento\Test\TestCase; + use Magento\Framework\Message\MessageInterface; use Magento\Framework\Stdlib\CookieManagerInterface; use Magento\Framework\View\Element\Message\InterpretationStrategyInterface; From 81632ff8800a7c05bd1e4116a42193cdee7cecbc Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Tue, 17 May 2016 20:14:32 +0300 Subject: [PATCH 21/30] MAGETWO-46014: delayed error messages --- app/code/Magento/Theme/Controller/Result/MessagePlugin.php | 2 +- .../Magento/TestFramework/TestCase/AbstractController.php | 2 +- .../testsuite/Magento/Paypal/Adminhtml/Paypal/ReportsTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/MessagePlugin.php b/app/code/Magento/Theme/Controller/Result/MessagePlugin.php index aae7731ca301e..ab9ae23133946 100644 --- a/app/code/Magento/Theme/Controller/Result/MessagePlugin.php +++ b/app/code/Magento/Theme/Controller/Result/MessagePlugin.php @@ -99,7 +99,7 @@ protected function getMessages() $messages = $this->getCookiesMessages(); /** @var MessageInterface $message */ foreach ($this->messageManager->getMessages(true)->getItems() as $message) { - $messages []= [ + $messages[] = [ 'type' => $message->getType(), 'text' => $this->interpretationStrategy->interpret($message), ]; diff --git a/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php b/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php index 622050dfc278a..44754d37d4055 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php +++ b/dev/tests/integration/framework/Magento/TestFramework/TestCase/AbstractController.php @@ -182,7 +182,7 @@ public function assertRedirect(\PHPUnit_Framework_Constraint $urlConstraint = nu } } - /**ishlist/Controller/IndexTest + /** * Assert that actual session messages meet expectations: * Usage examples: * $this->assertSessionMessages($this->isEmpty(), \Magento\Framework\Message\MessageInterface::TYPE_ERROR); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Adminhtml/Paypal/ReportsTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Adminhtml/Paypal/ReportsTest.php index c8660cb759bde..c18880325bb41 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Adminhtml/Paypal/ReportsTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Adminhtml/Paypal/ReportsTest.php @@ -23,7 +23,7 @@ public function testFetchAction() { $this->dispatch('backend/paypal/paypal_reports/fetch'); $this->assertSessionMessages( - $this->equalTo(['We can\'t fetch reports from "login@127.0.0.1."']), + $this->equalTo(['We can\'t fetch reports from "login@127.0.0.1."']), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); } From 492acabb2159e42f182eeb6cbd75476ea984fda0 Mon Sep 17 00:00:00 2001 From: Ihor Sytnykov Date: Thu, 19 May 2016 11:36:12 +0300 Subject: [PATCH 22/30] =?UTF-8?q?MDVA-275:=20Emails=20from=20admin=20being?= =?UTF-8?q?=20sent=20out=20using=20default=20config=E2=80=99s=20email,=20n?= =?UTF-8?q?ot=20the=20specific=20store=20email?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/code/Magento/Wishlist/Controller/Index/Send.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/Controller/Index/Send.php b/app/code/Magento/Wishlist/Controller/Index/Send.php index d286c4cccd43f..18b3c00456ec3 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Send.php +++ b/app/code/Magento/Wishlist/Controller/Index/Send.php @@ -185,8 +185,9 @@ public function execute() $sharingCode = $wishlist->getSharingCode(); try { + $storeId = $this->storeManager->getStore()->getStoreId(); + foreach ($emails as $email) { - $storeId = $this->storeManager->getStore()->getStoreId(); $transport = $this->_transportBuilder->setTemplateIdentifier( $this->scopeConfig->getValue( 'wishlist/email/email_template', From c6798e295996899788cbde13a72d32780095e091 Mon Sep 17 00:00:00 2001 From: Oleksii Kiselov Date: Thu, 19 May 2016 17:09:59 +0300 Subject: [PATCH 23/30] MDVA-228: Bulk product attribute update causes exception on store context change --- .../Controller/Adminhtml/Product/Action/Attribute/EditTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php index d329ec1aabafc..9ce9d43db7b60 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php @@ -1,7 +1,7 @@ Date: Thu, 19 May 2016 17:14:58 +0300 Subject: [PATCH 24/30] MDVA-228: Bulk product attribute update causes exception on store context change --- .../Controller/Adminhtml/Product/Action/Attribute/EditTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php index 9ce9d43db7b60..80661f48f5289 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Action/Attribute/EditTest.php @@ -1,6 +1,5 @@ Date: Fri, 3 Jun 2016 17:15:48 +0300 Subject: [PATCH 25/30] MDVA-457: Fatal error occurs in CLI command after compilation on some regression environments --- .../Module/Di/Code/Reader/ClassesScanner.php | 2 +- .../Module/Di/Code/Reader/FileScanner.php | 367 ++++++++++++++++++ 2 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php index ab3288fed4b53..74413dc5273df 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php @@ -6,7 +6,7 @@ namespace Magento\Setup\Module\Di\Code\Reader; use Magento\Framework\Exception\FileSystemException; -use Zend\Code\Scanner\FileScanner; +use Magento\Setup\Module\Di\Code\Reader\FileScanner; class ClassesScanner implements ClassesScannerInterface { diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php new file mode 100644 index 0000000000000..aacca3fbe71a5 --- /dev/null +++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php @@ -0,0 +1,367 @@ +isScanned) { + return; + } + + if (!$this->tokens) { + throw new \Zend\Code\Exception\RuntimeException('No tokens were provided'); + } + + /** + * Define PHP 5.4 'trait' token constant. + */ + if (!defined('T_TRAIT')) { + define('T_TRAIT', 42001); + } + + /** + * Variables & Setup + */ + + $tokens = &$this->tokens; // localize + $infos = &$this->infos; // localize + $tokenIndex = null; + $token = null; + $this->tokenType = null; + $tokenContent = null; + $tokenLine = null; + $namespace = null; + $docCommentIndex = false; + $infoIndex = 0; + + /* + * MACRO creation + */ + $MACRO_TOKEN_ADVANCE = function () use (&$tokens, &$tokenIndex, &$token, &$tokenContent, &$tokenLine) { + $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1; + if (!isset($tokens[$tokenIndex])) { + $token = false; + $tokenContent = false; + $this->tokenType = false; + $tokenLine = false; + + return false; + } + if (is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"') { + do { + $tokenIndex++; + } while (!(is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"')); + } + $token = $tokens[$tokenIndex]; + if (is_array($token)) { + list($this->tokenType, $tokenContent, $tokenLine) = $token; + } else { + $this->tokenType = null; + $tokenContent = $token; + } + + return $tokenIndex; + }; + $MACRO_TOKEN_LOGICAL_START_INDEX = function () use (&$tokenIndex, &$docCommentIndex) { + return ($docCommentIndex === false) ? $tokenIndex : $docCommentIndex; + }; + $MACRO_DOC_COMMENT_START = function () use (&$tokenIndex, &$docCommentIndex) { + $docCommentIndex = $tokenIndex; + + return $docCommentIndex; + }; + $MACRO_DOC_COMMENT_VALIDATE = function () use (&$docCommentIndex) { + static $validTrailingTokens = null; + if ($validTrailingTokens === null) { + $validTrailingTokens = array(T_WHITESPACE, T_FINAL, T_ABSTRACT, T_INTERFACE, T_CLASS, T_FUNCTION); + } + if ($docCommentIndex !== false && !in_array($this->tokenType, $validTrailingTokens)) { + $docCommentIndex = false; + } + + return $docCommentIndex; + }; + $MACRO_INFO_ADVANCE = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) { + $infos[$infoIndex]['tokenEnd'] = $tokenIndex; + $infos[$infoIndex]['lineEnd'] = $tokenLine; + $infoIndex++; + + return $infoIndex; + }; + + /** + * START FINITE STATE MACHINE FOR SCANNING TOKENS + */ + + // Initialize token + $MACRO_TOKEN_ADVANCE(); + + SCANNER_TOP: + + if ($token === false) { + goto SCANNER_END; + } + + // Validate current doc comment index + $MACRO_DOC_COMMENT_VALIDATE(); + + switch ($this->tokenType) { + + case T_DOC_COMMENT: + + $MACRO_DOC_COMMENT_START(); + goto SCANNER_CONTINUE; + //goto no break needed + + case T_NAMESPACE: + + $infos[$infoIndex] = array( + 'type' => 'namespace', + 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), + 'tokenEnd' => null, + 'lineStart' => $token[2], + 'lineEnd' => null, + 'namespace' => null, + ); + + // start processing with next token + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + + SCANNER_NAMESPACE_TOP: + + if ($this->tokenType === null && $tokenContent === ';' || $tokenContent === '{') { + goto SCANNER_NAMESPACE_END; + } + + if ($this->tokenType === T_WHITESPACE) { + goto SCANNER_NAMESPACE_CONTINUE; + } + + if ($this->tokenType === T_NS_SEPARATOR || $this->tokenType === T_STRING) { + $infos[$infoIndex]['namespace'] .= $tokenContent; + } + + SCANNER_NAMESPACE_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_NAMESPACE_TOP; + + SCANNER_NAMESPACE_END: + + $namespace = $infos[$infoIndex]['namespace']; + + $MACRO_INFO_ADVANCE(); + goto SCANNER_CONTINUE; + //goto no break needed + + case T_USE: + + $infos[$infoIndex] = array( + 'type' => 'use', + 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), + 'tokenEnd' => null, + 'lineStart' => $tokens[$tokenIndex][2], + 'lineEnd' => null, + 'namespace' => $namespace, + 'statements' => array(0 => array('use' => null, + 'as' => null)), + ); + + $useStatementIndex = 0; + $useAsContext = false; + + // start processing with next token + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + + SCANNER_USE_TOP: + + if ($this->tokenType === null) { + if ($tokenContent === ';') { + goto SCANNER_USE_END; + } elseif ($tokenContent === ',') { + $useAsContext = false; + $useStatementIndex++; + $infos[$infoIndex]['statements'][$useStatementIndex] = array('use' => null, + 'as' => null); + } + } + + // ANALYZE + if ($this->tokenType !== null) { + if ($this->tokenType == T_AS) { + $useAsContext = true; + goto SCANNER_USE_CONTINUE; + } + + if ($this->tokenType == T_NS_SEPARATOR || $this->tokenType == T_STRING) { + if ($useAsContext == false) { + $infos[$infoIndex]['statements'][$useStatementIndex]['use'] .= $tokenContent; + } else { + $infos[$infoIndex]['statements'][$useStatementIndex]['as'] = $tokenContent; + } + } + } + + SCANNER_USE_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_USE_TOP; + + SCANNER_USE_END: + + $MACRO_INFO_ADVANCE(); + goto SCANNER_CONTINUE; + //goto no break needed + + case T_INCLUDE: + case T_INCLUDE_ONCE: + case T_REQUIRE: + case T_REQUIRE_ONCE: + + // Static for performance + static $includeTypes = array( + T_INCLUDE => 'include', + T_INCLUDE_ONCE => 'include_once', + T_REQUIRE => 'require', + T_REQUIRE_ONCE => 'require_once' + ); + + $infos[$infoIndex] = array( + 'type' => 'include', + 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), + 'tokenEnd' => null, + 'lineStart' => $tokens[$tokenIndex][2], + 'lineEnd' => null, + 'includeType' => $includeTypes[$tokens[$tokenIndex][0]], + 'path' => '', + ); + + // start processing with next token + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + + SCANNER_INCLUDE_TOP: + + if ($this->tokenType === null && $tokenContent === ';') { + goto SCANNER_INCLUDE_END; + } + + $infos[$infoIndex]['path'] .= $tokenContent; + + SCANNER_INCLUDE_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_INCLUDE_TOP; + + SCANNER_INCLUDE_END: + + $MACRO_INFO_ADVANCE(); + goto SCANNER_CONTINUE; + //goto no break needed + + case T_FUNCTION: + case T_FINAL: + case T_ABSTRACT: + case T_CLASS: + case T_INTERFACE: + case T_TRAIT: + + $infos[$infoIndex] = array( + 'type' => ($this->tokenType === T_FUNCTION) ? 'function' : 'class', + 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), + 'tokenEnd' => null, + 'lineStart' => $tokens[$tokenIndex][2], + 'lineEnd' => null, + 'namespace' => $namespace, + 'uses' => $this->getUsesNoScan($namespace), + 'name' => null, + 'shortName' => null, + ); + + $classBraceCount = 0; + + // start processing with current token + + SCANNER_CLASS_TOP: + + // process the name + if ($infos[$infoIndex]['shortName'] == '' + && (($this->tokenType === T_CLASS || $this->tokenType === T_INTERFACE || $this->tokenType === T_TRAIT) && $infos[$infoIndex]['type'] === 'class' + || ($this->tokenType === T_FUNCTION && $infos[$infoIndex]['type'] === 'function')) + ) { + $infos[$infoIndex]['shortName'] = $tokens[$tokenIndex + 2][1]; + $infos[$infoIndex]['name'] = (($namespace !== null) ? $namespace . '\\' : '') . $infos[$infoIndex]['shortName']; + } + + if ($this->tokenType === null) { + if ($tokenContent == '{') { + $classBraceCount++; + } + if ($tokenContent == '}') { + $classBraceCount--; + if ($classBraceCount === 0) { + goto SCANNER_CLASS_END; + } + } + } + + SCANNER_CLASS_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_CLASS_TOP; + + SCANNER_CLASS_END: + + $MACRO_INFO_ADVANCE(); + goto SCANNER_CONTINUE; + + } + + SCANNER_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_TOP; + + SCANNER_END: + + /** + * END FINITE STATE MACHINE FOR SCANNING TOKENS + */ + + $this->isScanned = true; + } +} From 9fc4c15ea274caea68f7dc10b5ea625e0591fa3f Mon Sep 17 00:00:00 2001 From: Anna Bukatar Date: Fri, 17 Jun 2016 18:56:20 +0300 Subject: [PATCH 26/30] =?UTF-8?q?MDVA-275:=20Emails=20from=20admin=20being?= =?UTF-8?q?=20sent=20out=20using=20default=20config=E2=80=99s=20email,=20n?= =?UTF-8?q?ot=20the=20specific=20store=20email?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed test case from MDVA-452: Issue with sender email addresses in admin sales for multiple stores and websites --- app/code/Magento/Sales/Model/Order/Email/SenderBuilder.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Sales/Model/Order/Email/SenderBuilder.php b/app/code/Magento/Sales/Model/Order/Email/SenderBuilder.php index ed58a69c91cd7..bed8b15ca65fa 100644 --- a/app/code/Magento/Sales/Model/Order/Email/SenderBuilder.php +++ b/app/code/Magento/Sales/Model/Order/Email/SenderBuilder.php @@ -95,6 +95,7 @@ public function sendCopyTo() */ protected function configureEmailTemplate() { + $this->transportBuilder->setScopeId($this->identityContainer->getStore()->getStoreId()); $this->transportBuilder->setTemplateIdentifier($this->templateContainer->getTemplateId()); $this->transportBuilder->setTemplateOptions($this->templateContainer->getTemplateOptions()); $this->transportBuilder->setTemplateVars($this->templateContainer->getTemplateVars()); From 8fde6d3e456db864d9ffe89920f4f5d3649b20e7 Mon Sep 17 00:00:00 2001 From: Oleksii Kiselov Date: Wed, 22 Jun 2016 15:12:42 +0300 Subject: [PATCH 27/30] MDVA-460: Duplicating url keys on creating configurable product --- .../CatalogImportExport/Model/Import/Product.php | 16 +++++++++++++++- .../Model/Category/Plugin/Store/Group.php | 2 +- .../Model/Category/Plugin/Store/View.php | 2 +- .../Model/ProductUrlRewriteGenerator.php | 5 +++++ .../Observer/AfterImportDataObserver.php | 9 +++++++++ .../ProductProcessUrlRewriteSavingObserver.php | 5 +++-- .../Observer/UrlRewriteHandler.php | 2 ++ 7 files changed, 36 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 6f4c6d1f53a15..c2fe86a8ec4c4 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -16,6 +16,7 @@ use Magento\ImportExport\Model\Import; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingError; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; +use Magento\Catalog\Model\Product\Visibility; /** * Import entity product model @@ -2237,7 +2238,8 @@ public function validateRow(array $rowData, $rowNum) } // validate custom options $this->getOptionEntity()->validateRow($rowData, $rowNum); - if (!empty($rowData[self::URL_KEY]) || !empty($rowData[self::COL_NAME])) { + + if ($this->isNeedToValidateUrlKey($rowData)) { $urlKey = $this->getUrlKey($rowData); $storeCodes = empty($rowData[self::COL_STORE_VIEW_CODE]) ? array_flip($this->storeResolver->getStoreCodeToId()) @@ -2259,6 +2261,18 @@ public function validateRow(array $rowData, $rowNum) return !$this->getErrorAggregator()->isRowInvalid($rowNum); } + /** + * @param array $rowData + * @return bool + */ + private function isNeedToValidateUrlKey($rowData) + { + return (!empty($rowData[self::URL_KEY]) || !empty($rowData[self::COL_NAME])) + && (empty($rowData['visibility']) + || $rowData['visibility'] + !== (string)Visibility::getOptionArray()[Visibility::VISIBILITY_NOT_VISIBLE]); + } + /** * Parse attributes names and values string to array. * diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php index 5892371a4ec29..f3c86bad49936 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php @@ -113,7 +113,7 @@ protected function generateProductUrls($websiteId, $originWebsiteId) $collection = $this->productFactory->create() ->getCollection() ->addCategoryIds() - ->addAttributeToSelect(['name', 'url_path', 'url_key']) + ->addAttributeToSelect(['name', 'url_path', 'url_key', 'visibility']) ->addWebsiteFilter($websiteIds); foreach ($collection as $product) { /** @var \Magento\Catalog\Model\Product $product */ diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php index df9af24075a48..ade02f8446921 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php @@ -100,7 +100,7 @@ protected function generateProductUrls($websiteId, $originWebsiteId, $storeId) $collection = $this->productFactory->create() ->getCollection() ->addCategoryIds() - ->addAttributeToSelect(['name', 'url_path', 'url_key']) + ->addAttributeToSelect(['name', 'url_path', 'url_key', 'visibility']) ->addWebsiteFilter($websiteIds); foreach ($collection as $product) { $product->setStoreId($storeId); diff --git a/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlRewriteGenerator.php b/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlRewriteGenerator.php index 6dc4ab0f95c6f..098ac4a88391a 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlRewriteGenerator.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlRewriteGenerator.php @@ -11,6 +11,7 @@ use Magento\CatalogUrlRewrite\Model\Product\CurrentUrlRewritesRegenerator; use Magento\CatalogUrlRewrite\Service\V1\StoreViewService; use Magento\Store\Model\Store; +use Magento\Catalog\Model\Product\Visibility; class ProductUrlRewriteGenerator { @@ -75,6 +76,10 @@ public function __construct( */ public function generate(Product $product) { + if ($product->getVisibility() == Visibility::VISIBILITY_NOT_VISIBLE) { + return []; + } + $this->product = $product; $storeId = $this->product->getStoreId(); diff --git a/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php b/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php index 49c91b1e891fe..0f2a00b7ebfc1 100644 --- a/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php +++ b/app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php @@ -19,6 +19,7 @@ use Magento\UrlRewrite\Model\OptionProvider; use Magento\UrlRewrite\Model\UrlFinderInterface; use Magento\Framework\Event\ObserverInterface; +use Magento\Catalog\Model\Product\Visibility; /** * Class AfterImportDataObserver @@ -93,6 +94,7 @@ class AfterImportDataObserver implements ObserverInterface 'url_key', 'url_path', 'name', + 'visibility', ]; /** @@ -221,6 +223,10 @@ protected function setStoreToProduct(\Magento\Catalog\Model\Product $product, ar */ protected function addProductToImport($product, $storeId) { + if ($product->getVisibility() == (string)Visibility::getOptionArray()[Visibility::VISIBILITY_NOT_VISIBLE]) { + return $this; + } + if (!isset($this->products[$product->getId()])) { $this->products[$product->getId()] = []; } @@ -321,6 +327,9 @@ protected function categoriesUrlRewriteGenerate() foreach ($productsByStores as $storeId => $product) { foreach ($this->categoryCache[$productId] as $categoryId) { $category = $this->import->getCategoryProcessor()->getCategoryById($categoryId); + if ($category->getParentId() == Category::TREE_ROOT_ID) { + continue; + } $requestPath = $this->productUrlPathGenerator->getUrlPathWithSuffix($product, $storeId, $category); $urls[] = $this->urlRewriteFactory->create() ->setEntityType(ProductUrlRewriteGenerator::ENTITY_TYPE) diff --git a/app/code/Magento/CatalogUrlRewrite/Observer/ProductProcessUrlRewriteSavingObserver.php b/app/code/Magento/CatalogUrlRewrite/Observer/ProductProcessUrlRewriteSavingObserver.php index 75a63ab0c9727..2b7bfe017455b 100644 --- a/app/code/Magento/CatalogUrlRewrite/Observer/ProductProcessUrlRewriteSavingObserver.php +++ b/app/code/Magento/CatalogUrlRewrite/Observer/ProductProcessUrlRewriteSavingObserver.php @@ -47,14 +47,15 @@ public function execute(\Magento\Framework\Event\Observer $observer) $product = $observer->getEvent()->getProduct(); $isChangedWebsites = $product->getIsChangedWebsites(); - if ($product->dataHasChangedFor('url_key') || $product->getIsChangedCategories() || $isChangedWebsites) { + if ($product->dataHasChangedFor('url_key') || $product->getIsChangedCategories() || $isChangedWebsites + || $product->dataHasChangedFor('visibility')) { if ($isChangedWebsites) { $this->urlPersist->deleteByData([ UrlRewrite::ENTITY_ID => $product->getId(), UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE, ]); } - if ($product->getVisibility() != Visibility::VISIBILITY_NOT_VISIBLE) { + if (!in_array($product->getOrigData('visibility'), $product->getVisibleInSiteVisibilities())) { $this->urlPersist->replace($this->productUrlRewriteGenerator->generate($product)); } } diff --git a/app/code/Magento/CatalogUrlRewrite/Observer/UrlRewriteHandler.php b/app/code/Magento/CatalogUrlRewrite/Observer/UrlRewriteHandler.php index cd044d6e6fc87..b02ef76d95146 100644 --- a/app/code/Magento/CatalogUrlRewrite/Observer/UrlRewriteHandler.php +++ b/app/code/Magento/CatalogUrlRewrite/Observer/UrlRewriteHandler.php @@ -70,6 +70,7 @@ public function generateProductUrlRewrites(Category $category) $collection = $this->productCollectionFactory->create() ->setStoreId($storeId) ->addIdFilter($category->getAffectedProductIds()) + ->addAttributeToSelect('visibility') ->addAttributeToSelect('name') ->addAttributeToSelect('url_key') ->addAttributeToSelect('url_path'); @@ -104,6 +105,7 @@ public function getCategoryProductsUrlRewrites(Category $category, $storeId, $sa /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection */ $productCollection = $category->getProductCollection() ->addAttributeToSelect('name') + ->addAttributeToSelect('visibility') ->addAttributeToSelect('url_key') ->addAttributeToSelect('url_path'); $productUrls = []; From 47cdb267290e9cc356e1721931c03db4bbe1e012 Mon Sep 17 00:00:00 2001 From: Oleksii Kiselov Date: Wed, 22 Jun 2016 17:44:49 +0300 Subject: [PATCH 28/30] MDVA-460: Duplicating url keys on creating configurable product --- .../CatalogUrlRewrite/Model/Category/Plugin/Store/View.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php index ade02f8446921..860e5480988ca 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php @@ -14,6 +14,9 @@ use Magento\UrlRewrite\Model\UrlPersistInterface; use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class View { /** @var UrlPersistInterface */ From d6d6265ce0c8979ea0487fbfb16d2a84ded38b99 Mon Sep 17 00:00:00 2001 From: "Bukatar, Anna" Date: Fri, 1 Jul 2016 13:05:30 +0300 Subject: [PATCH 29/30] =?UTF-8?q?MDVA-275:=20Emails=20from=20admin=20being?= =?UTF-8?q?=20sent=20out=20using=20default=20config=E2=80=99s=20email,=20n?= =?UTF-8?q?ot=20the=20specific=20store=20email?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed unit test error --- .../Test/Unit/Model/Order/Email/SenderBuilderTest.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/SenderBuilderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/SenderBuilderTest.php index 1c0e42b28695f..8d5575fbdea9d 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/SenderBuilderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/SenderBuilderTest.php @@ -29,6 +29,11 @@ class SenderBuilderTest extends \PHPUnit_Framework_TestCase */ protected $transportBuilder; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeMock; + protected function setUp() { $templateId = 'test_template_id'; @@ -58,7 +63,7 @@ protected function setUp() [ 'getEmailIdentity', 'getCustomerEmail', 'getCustomerName', 'getTemplateOptions', 'getEmailCopyTo', - 'getCopyMethod' + 'getCopyMethod', 'getStore' ], [], '', @@ -99,6 +104,9 @@ protected function setUp() $this->identityContainerMock->expects($this->once()) ->method('getEmailIdentity') ->will($this->returnValue($emailIdentity)); + $this->identityContainerMock->expects($this->once()) + ->method('getStore') + ->will($this->returnValue($this->storeMock)); $this->transportBuilder->expects($this->once()) ->method('setFrom') ->with($this->equalTo($emailIdentity)); From e49975db6546e912e9f17661794155a1de4467ac Mon Sep 17 00:00:00 2001 From: Ihor Sytnykov Date: Fri, 8 Jul 2016 14:05:45 +0300 Subject: [PATCH 30/30] MDVA-373: Error upon adding product to cart --- .../testsuite/Magento/Catalog/_files/product_simple_xss.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_xss.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_xss.php index 515c180c062a5..bb982398f8d39 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_xss.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_xss.php @@ -16,7 +16,7 @@ )->setName( '' )->setSku( - '' + 'product-with-xss' )->setPrice( 10 )->setDescription(