From 0aa02fe934efc73f36169d6181713474b5aeb563 Mon Sep 17 00:00:00 2001 From: Justin Sims Date: Tue, 21 Jan 2020 09:28:54 -0500 Subject: [PATCH 001/120] Adjusted TransportBuilder prepareMessage method to support text/plain template emails --- .../Magento/Framework/Mail/Template/TransportBuilder.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 830d9b0f722e4..c423d6ec627bb 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -394,7 +394,12 @@ protected function prepareMessage() } /** @var \Magento\Framework\Mail\MimePartInterface $mimePart */ - $mimePart = $this->mimePartInterfaceFactory->create(['content' => $content]); + $mimePart = $this->mimePartInterfaceFactory->create( + [ + 'content' => $content, + 'type' => $part['type'] + ] + ); $this->messageData['encoding'] = $mimePart->getCharset(); $this->messageData['body'] = $this->mimeMessageInterfaceFactory->create( ['parts' => [$mimePart]] From f2b46df5b6a681d63e4254abdb13b49733574db1 Mon Sep 17 00:00:00 2001 From: Marvin Hinz <35603466+marvinhinz@users.noreply.github.com> Date: Wed, 29 Jan 2020 10:26:40 +0100 Subject: [PATCH 002/120] Improve developer experience: RuntimeException thrown by AbstractFactory::createObject now contains the reason. This implements feature request #26550 --- .../Magento/Framework/ObjectManager/Factory/AbstractFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php b/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php index 7094b116ead3f..6df29261998bb 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php +++ b/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php @@ -129,7 +129,7 @@ protected function createObject($type, $args) ); throw new RuntimeException( - new Phrase('Type Error occurred when creating object: %type', ['type' => $type]) + new Phrase('Type Error occurred when creating object: %type, %msg', ['type' => $type, 'msg' => $exception->getMessage()]) ); } } From 00971d065a6cc353b83ace91dd65f06efe2640fe Mon Sep 17 00:00:00 2001 From: Marvin Hinz <35603466+marvinhinz@users.noreply.github.com> Date: Fri, 7 Feb 2020 13:23:06 +0100 Subject: [PATCH 003/120] Fix code check for max line length --- .../Framework/ObjectManager/Factory/AbstractFactory.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php b/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php index 6df29261998bb..735b9454bbfa1 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php +++ b/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php @@ -129,7 +129,10 @@ protected function createObject($type, $args) ); throw new RuntimeException( - new Phrase('Type Error occurred when creating object: %type, %msg', ['type' => $type, 'msg' => $exception->getMessage()]) + new Phrase('Type Error occurred when creating object: %type, %msg', [ + 'type' => $type, + 'msg' => $exception->getMessage() + ]) ); } } From b4c2cc5a1df3ff1b4dd5646db1f8125fd8c1fceb Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya Date: Thu, 13 Feb 2020 12:41:02 +0530 Subject: [PATCH 004/120] Fixed transaction issues --- app/code/Magento/Backend/etc/adminhtml/system.xml | 10 ++++------ app/code/Magento/Backend/i18n/en_US.csv | 6 +----- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml index 3a2b3554cc4a0..45ed50fd49b7e 100644 --- a/app/code/Magento/Backend/etc/adminhtml/system.xml +++ b/app/code/Magento/Backend/etc/adminhtml/system.xml @@ -115,7 +115,7 @@ Magento\Config\Model\Config\Source\Yesno - + 1 @@ -123,7 +123,7 @@ Magento\Config\Model\Config\Source\Yesno Use URL parameter to enable template path hints for Storefront - + 1 @@ -341,7 +341,7 @@ - + Magento\Config\Model\Config\Source\Yesno Resize performed via javascript before file upload. @@ -459,9 +459,7 @@ Magento\Config\Model\Config\Source\Yesno Magento\Config\Model\Config\Backend\Store - - Warning! When using Store Code in URLs, in some cases system may not work properly if URLs without Store Codes are specified in the third-party services (e.g. PayPal etc.).]]> - + Warning! When using Store Code in URLs, in some cases system may not work properly if URLs without Store Codes are specified in the third-party services (e.g. PayPal etc.).]]> diff --git a/app/code/Magento/Backend/i18n/en_US.csv b/app/code/Magento/Backend/i18n/en_US.csv index 51fe8bfe542a2..d073c71aa6515 100644 --- a/app/code/Magento/Backend/i18n/en_US.csv +++ b/app/code/Magento/Backend/i18n/en_US.csv @@ -404,11 +404,7 @@ Security,Security Web,Web "Url Options","Url Options" "Add Store Code to Urls","Add Store Code to Urls" -" - Warning! When using Store Code in URLs, in some cases system may not work properly if URLs without Store Codes are specified in the third-party services (e.g. PayPal etc.). - "," - Warning! When using Store Code in URLs, in some cases system may not work properly if URLs without Store Codes are specified in the third-party services (e.g. PayPal etc.). - " +"Warning! When using Store Code in URLs, in some cases system may not work properly if URLs without Store Codes are specified in the third-party services (e.g. PayPal etc.).","Warning! When using Store Code in URLs, in some cases system may not work properly if URLs without Store Codes are specified in the third-party services (e.g. PayPal etc.)." "Auto-redirect to Base URL","Auto-redirect to Base URL" "Search Engine Optimization","Search Engine Optimization" "Use Web Server Rewrites","Use Web Server Rewrites" From 3658a1ba09b00111c7563471b23eb05fb2f75a9a Mon Sep 17 00:00:00 2001 From: Alok Patel Date: Tue, 3 Mar 2020 15:21:27 +0530 Subject: [PATCH 005/120] Update AbstractResource.php --- .../Framework/Model/ResourceModel/AbstractResource.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php index 255e6d94d741f..555a73577e6f6 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php @@ -92,12 +92,12 @@ public function commit() */ if ($this->getConnection()->getTransactionLevel() === 0) { $callbacks = CallbackPool::get(spl_object_hash($this->getConnection())); - try { - foreach ($callbacks as $callback) { - call_user_func($callback); - } - } catch (\Exception $e) { + foreach ($callbacks as $callback) { + try { + call_user_func($callback); + } catch (\Exception $e) { $this->getLogger()->critical($e); + } } } return $this; From 2ef402a91a88c098db11a1024940ada4c842d16e Mon Sep 17 00:00:00 2001 From: "vadim.malesh" Date: Mon, 16 Mar 2020 09:47:43 +0200 Subject: [PATCH 006/120] fix static, test coverage --- .../Model/ResourceModel/AbstractResource.php | 12 +- .../ResourceModel/AbstractResourceTest.php | 183 +++++++++++++----- 2 files changed, 138 insertions(+), 57 deletions(-) diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php index 555a73577e6f6..51a59df3383af 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php @@ -13,6 +13,7 @@ /** * Abstract resource model * + * phpcs:disable Magento2.Classes.AbstractApi * @api */ abstract class AbstractResource @@ -93,13 +94,14 @@ public function commit() if ($this->getConnection()->getTransactionLevel() === 0) { $callbacks = CallbackPool::get(spl_object_hash($this->getConnection())); foreach ($callbacks as $callback) { - try { - call_user_func($callback); - } catch (\Exception $e) { - $this->getLogger()->critical($e); - } + try { + call_user_func($callback); + } catch (\Exception $e) { + $this->getLogger()->critical($e); + } } } + return $this; } diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php index 11917d4df1973..4f979f554d3ee 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/AbstractResourceTest.php @@ -3,67 +3,83 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Framework\Model\Test\Unit\ResourceModel; use Magento\Framework\DataObject; use Magento\Framework\DB\Adapter\AdapterInterface; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\MockObject\MockObject as MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; -class AbstractResourceTest extends \PHPUnit\Framework\TestCase +/** + * Test for \Magento\Framework\Model\ResourceModel\AbstractResource. + */ +class AbstractResourceTest extends TestCase { /** * @var AbstractResourceStub */ - private $abstractResource; + private $model; /** - * @var Json|\PHPUnit_Framework_MockObject_MockObject + * @var Json|MockObject */ private $serializerMock; /** - * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var LoggerInterface|MockObject */ private $loggerMock; + /** + * @inheritdoc + */ protected function setUp() { $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject(AbstractResourceStub::class); $this->serializerMock = $this->createMock(Json::class); - $this->loggerMock = $this->createMock(\Psr\Log\LoggerInterface::class); - $this->abstractResource = $objectManager->getObject(AbstractResourceStub::class); - $objectManager->setBackwardCompatibleProperty($this->abstractResource, 'serializer', $this->serializerMock); - $objectManager->setBackwardCompatibleProperty($this->abstractResource, '_logger', $this->loggerMock); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $objectManager->setBackwardCompatibleProperty($this->model, 'serializer', $this->serializerMock); + $objectManager->setBackwardCompatibleProperty($this->model, '_logger', $this->loggerMock); } /** + * Test fields serialize + * * @param array $arguments - * @param string $expected + * @param string|null $expected * @param array|string|int $serializeCalledWith * @param int $numSerializeCalled + * @return void * @dataProvider serializeFieldsDataProvider */ public function testSerializeFields( array $arguments, - $expected, + ?string $expected, $serializeCalledWith, - $numSerializeCalled = 1 - ) { + int $numSerializeCalled = 1 + ): void { /** @var DataObject $dataObject */ - list($dataObject, $field, $defaultValue, $unsetEmpty) = $arguments; + [$dataObject, $field, $defaultValue, $unsetEmpty] = $arguments; $this->serializerMock->expects($this->exactly($numSerializeCalled)) ->method('serialize') ->with($serializeCalledWith) ->willReturn($expected); - $this->abstractResource->_serializeField($dataObject, $field, $defaultValue, $unsetEmpty); + $this->model->_serializeField($dataObject, $field, $defaultValue, $unsetEmpty); $this->assertEquals($expected, $dataObject->getData($field)); } /** + * DataProvider for testSerializeFields() + * * @return array */ - public function serializeFieldsDataProvider() + public function serializeFieldsDataProvider(): array { $array = ['a', 'b', 'c']; $string = 'i am string'; @@ -75,60 +91,66 @@ public function serializeFieldsDataProvider() 'string' => $string, 'integer' => $integer, 'empty' => $empty, - 'empty_with_default' => '' + 'empty_with_default' => '', ] ); + return [ [ [$dataObject, 'array', null, false], '["a","b","c"]', - $array + $array, ], [ [$dataObject, 'string', null, false], '"i am string"', - $string + $string, ], [ [$dataObject, 'integer', null, false], '969', - $integer + $integer, ], [ [$dataObject, 'empty', null, true], null, $empty, - 0 + 0, ], [ [$dataObject, 'empty_with_default', 'default', false], '"default"', - 'default' - ] + 'default', + ], ]; } /** + * Test fields unserialize + * * @param array $arguments * @param array|string|int|boolean $expected + * @return void * @dataProvider unserializeFieldsDataProvider */ - public function testUnserializeFields(array $arguments, $expected) + public function testUnserializeFields(array $arguments, $expected): void { /** @var DataObject $dataObject */ - list($dataObject, $field, $defaultValue) = $arguments; + [$dataObject, $field, $defaultValue] = $arguments; $this->serializerMock->expects($this->once()) ->method('unserialize') ->with($dataObject->getData($field)) ->willReturn($expected); - $this->abstractResource->_unserializeField($dataObject, $field, $defaultValue); + $this->model->_unserializeField($dataObject, $field, $defaultValue); $this->assertEquals($expected, $dataObject->getData($field)); } /** + * DataProvider for testUnserializeFields() + * * @return array */ - public function unserializeFieldsDataProvider() + public function unserializeFieldsDataProvider(): array { $dataObject = new DataObject( [ @@ -137,54 +159,60 @@ public function unserializeFieldsDataProvider() 'integer' => '969', 'empty_with_default' => '""', 'not_serialized_string' => 'i am string', - 'serialized_boolean_false' => 'false' + 'serialized_boolean_false' => 'false', ] ); + return [ [ [$dataObject, 'array', null], - ['a', 'b', 'c'] + ['a', 'b', 'c'], ], [ [$dataObject, 'string', null], - 'i am string' + 'i am string', ], [ [$dataObject, 'integer', null], - 969 + 969, ], [ [$dataObject, 'empty_with_default', 'default', false], - 'default' + 'default', ], [ [$dataObject, 'not_serialized_string', null], - 'i am string' + 'i am string', ], [ [$dataObject, 'serialized_boolean_false', null], false, - ] + ], ]; } - - public function testCommitZeroLevel() + + /** + * Commit zero level + * + * @return void + */ + public function testCommitZeroLevel(): void { - /** @var AdapterInterface|\PHPUnit_Framework_MockObject_MockObject $connection */ + /** @var AdapterInterface|MockObject $connection */ $connection = $this->createMock(AdapterInterface::class); - /** @var DataObject|\PHPUnit_Framework_MockObject_MockObject $closureExpectation */ + /** @var DataObject|MockObject $closureExpectation */ $closureExpectation = $this->getMockBuilder(DataObject::class) ->disableOriginalConstructor() ->getMock(); - $this->abstractResource->setConnection($connection); - $this->abstractResource->addCommitCallback( + $this->model->setConnection($connection); + $this->model->addCommitCallback( function () use ($closureExpectation) { $closureExpectation->setData(1); } ); - $this->abstractResource->addCommitCallback( + $this->model->addCommitCallback( function () use ($closureExpectation) { $closureExpectation->getData(); } @@ -201,16 +229,21 @@ function () use ($closureExpectation) { $closureExpectation->expects($this->once()) ->method('getData'); - $this->abstractResource->commit(); + $this->model->commit(); } - public function testCommitZeroLevelCallbackException() + /** + * Commit zero level callback with exception + * + * @return void + */ + public function testCommitZeroLevelCallbackException(): void { /** @var AdapterInterface|\PHPUnit_Framework_MockObject_MockObject $connection */ $connection = $this->createMock(AdapterInterface::class); - $this->abstractResource->setConnection($connection); - $this->abstractResource->addCommitCallback( + $this->model->setConnection($connection); + $this->model->addCommitCallback( function () { throw new \Exception(); } @@ -224,20 +257,25 @@ function () { $this->loggerMock->expects($this->once()) ->method('critical'); - $this->abstractResource->commit(); + $this->model->commit(); } - public function testCommitNotCompletedTransaction() + /** + * Commit of transactions that have not been completed + * + * @return void + */ + public function testCommitNotCompletedTransaction(): void { - /** @var AdapterInterface|\PHPUnit_Framework_MockObject_MockObject $connection */ + /** @var AdapterInterface|MockObject $connection */ $connection = $this->createMock(AdapterInterface::class); - /** @var DataObject|\PHPUnit_Framework_MockObject_MockObject $closureExpectation */ + /** @var DataObject|MockObject $closureExpectation */ $closureExpectation = $this->getMockBuilder(DataObject::class) ->disableOriginalConstructor() ->getMock(); - $this->abstractResource->setConnection($connection); - $this->abstractResource->addCommitCallback( + $this->model->setConnection($connection); + $this->model->addCommitCallback( function () use ($closureExpectation) { $closureExpectation->setData(1); } @@ -253,6 +291,47 @@ function () use ($closureExpectation) { ->method('setData') ->with(1); - $this->abstractResource->commit(); + $this->model->commit(); + } + + /** + * Test commit case when first callback throws an exception but other callbacks will be called + * + * @return void + */ + public function testCommitFewCallbacksWithException(): void + { + /** @var AdapterInterface|MockObject $connection */ + $connection = $this->createMock(AdapterInterface::class); + + /** @var DataObject|MockObject $closureExpectation */ + $closureExpectation = $this->getMockBuilder(DataObject::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model->setConnection($connection); + $this->model->addCommitCallback( + function () { + throw new \Exception(); + } + ); + + $this->model->addCommitCallback( + function () use ($closureExpectation) { + $closureExpectation->getData(); + } + ); + + $connection->expects($this->once()) + ->method('commit'); + $connection->expects($this->once()) + ->method('getTransactionLevel') + ->willReturn(0); + $this->loggerMock->expects($this->once()) + ->method('critical'); + $closureExpectation->expects($this->once()) + ->method('getData'); + + $this->model->commit(); } } From 31eeaa7b5b18d27fc786660d23faaba6ff0393d1 Mon Sep 17 00:00:00 2001 From: Mateusz Krzeszowiak Date: Thu, 12 Mar 2020 20:16:06 +0100 Subject: [PATCH 007/120] Adjust mechanism that moves all scripts to the end of the page --- .../Controller/Result/JsFooterPlugin.php | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php index 6a80dec460660..9a68e28942056 100644 --- a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -40,25 +40,32 @@ public function __construct(ScopeConfigInterface $scopeConfig) public function beforeSendResponse(Http $subject) { $content = $subject->getContent(); - $script = []; - if (is_string($content) && strpos($content, 'scopeConfig->isSetFlag( - self::XML_PATH_DEV_MOVE_JS_TO_BOTTOM, - ScopeInterface::SCOPE_STORE - ) - ) { - $pattern = '#]*+(?.*?#is'; - $content = preg_replace_callback( - $pattern, - function ($matchPart) use (&$script) { - $script[] = $matchPart[0]; - return ''; - }, - $content - ); - $subject->setContent( - str_replace('scopeConfig->isSetFlag( + self::XML_PATH_DEV_MOVE_JS_TO_BOTTOM, + ScopeInterface::SCOPE_STORE + )) { + $scripts = ''; + + $scriptOpen = 'setContent($content); } } } From 4fa54472bab13709e6f320fea97bdc94f330bcfd Mon Sep 17 00:00:00 2001 From: Mateusz Krzeszowiak Date: Wed, 18 Mar 2020 21:30:45 +0100 Subject: [PATCH 008/120] Don't move Magento templates, fix tests --- .../Magento/Theme/Controller/Result/JsFooterPlugin.php | 7 ++++++- .../Test/Unit/Controller/Result/JsFooterPluginTest.php | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php index 9a68e28942056..07c72f6692cc2 100644 --- a/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/JsFooterPlugin.php @@ -39,7 +39,7 @@ public function __construct(ScopeConfigInterface $scopeConfig) */ public function beforeSendResponse(Http $subject) { - $content = $subject->getContent(); + $content = $subject->getContent() ?? ''; $bodyClose = ' true, "result" => "

Test Title

" . "" . - "

Test Content

" . - "" . - "\n" + "

Test Content

\n" . + "\n" . + "" ], 'content_with_config_disable' => [ "content" => "

Test Content

", From 0e964e496c0d83ab20974da51f2d21ba2680043e Mon Sep 17 00:00:00 2001 From: Rohan Hapani Date: Fri, 20 Mar 2020 14:49:05 +0530 Subject: [PATCH 009/120] Solution : Advance search page allow minus price filter --- .../CatalogSearch/view/frontend/templates/advanced/form.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogSearch/view/frontend/templates/advanced/form.phtml b/app/code/Magento/CatalogSearch/view/frontend/templates/advanced/form.phtml index 3712f221233ee..26420705c7ffd 100644 --- a/app/code/Magento/CatalogSearch/view/frontend/templates/advanced/form.phtml +++ b/app/code/Magento/CatalogSearch/view/frontend/templates/advanced/form.phtml @@ -68,7 +68,7 @@ class="input-text" type="text" maxlength="escapeHtmlAttr($maxQueryLength) ?>" - data-validate="{number:true, 'less-than-equals-to':'#escapeHtmlAttr($_code) ?>_to'}" /> + data-validate="{number:true, 'validate-not-negative-number':true, 'less-than-equals-to':'#escapeHtmlAttr($_code) ?>_to'}" />
@@ -81,7 +81,7 @@ class="input-text" type="text" maxlength="escapeHtmlAttr($maxQueryLength) ?>" - data-validate="{number:true, 'greater-than-equals-to':'#escapeHtmlAttr($_code) ?>'}" /> + data-validate="{number:true, 'validate-not-negative-number':true, 'greater-than-equals-to':'#escapeHtmlAttr($_code) ?>'}" />