From 05c7acbde36963233220c53952891a53ec70ee8e Mon Sep 17 00:00:00 2001 From: Igor Melnikov Date: Fri, 18 Dec 2015 15:12:12 -0600 Subject: [PATCH 01/23] MAGETWO-45723: Plugins methods calls two times in case when Proxy exists for subject class Adding NoninterceptableInterface to allow skip interceptor generation --- .../Config/Structure/Element/Group/Proxy.php | 3 +- .../Model/Config/Structure/Search/Proxy.php | 4 +- .../SourceClassWithNamespaceProxy.php.sample | 2 +- .../Magento/Framework/App/AreaList/Proxy.php | 3 +- .../Magento/Framework/App/Cache/Proxy.php | 12 ++-- .../App/Route/ConfigInterface/Proxy.php | 4 +- .../DataObject/Copy/Config/Data/Proxy.php | 3 +- .../ObjectManager/Config/Developer.php | 26 +++++++- .../Framework/Mview/Config/Data/Proxy.php | 3 +- .../ObjectManager/Code/Generator/Proxy.php | 8 ++- .../ObjectManager/InterceptableValidator.php | 59 +++++++++++++++++++ .../NoninterceptableInterface.php | 13 ++++ .../Code/Generator/_files/SampleProxy.txt | 2 +- .../Test/Unit/InterceptableValidatorTest.php | 26 ++++++++ .../ObjectManager/Test/Unit/_files/Proxy.php | 10 ++++ .../Framework/Translate/Inline/Proxy.php | 4 +- .../Magento/Framework/View/Layout/Proxy.php | 2 +- .../Command/DiCompileMultiTenantCommand.php | 4 +- .../InterceptionConfigurationBuilder.php | 15 ++++- .../Scanner/InheritanceInterceptorScanner.php | 33 +++++------ .../InterceptionConfigurationBuilderTest.php | 20 ++++++- 21 files changed, 217 insertions(+), 39 deletions(-) create mode 100644 lib/internal/Magento/Framework/ObjectManager/InterceptableValidator.php create mode 100644 lib/internal/Magento/Framework/ObjectManager/NoninterceptableInterface.php create mode 100644 lib/internal/Magento/Framework/ObjectManager/Test/Unit/InterceptableValidatorTest.php create mode 100644 lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/Proxy.php diff --git a/app/code/Magento/Config/Model/Config/Structure/Element/Group/Proxy.php b/app/code/Magento/Config/Model/Config/Structure/Element/Group/Proxy.php index 1b3aeca06effc..7365fade4caa3 100644 --- a/app/code/Magento/Config/Model/Config/Structure/Element/Group/Proxy.php +++ b/app/code/Magento/Config/Model/Config/Structure/Element/Group/Proxy.php @@ -5,7 +5,8 @@ */ namespace Magento\Config\Model\Config\Structure\Element\Group; -class Proxy extends \Magento\Config\Model\Config\Structure\Element\Group +class Proxy extends \Magento\Config\Model\Config\Structure\Element\Group implements + \Magento\Framework\ObjectManager\NoninterceptableInterface { /** * Object manager diff --git a/app/code/Magento/Config/Model/Config/Structure/Search/Proxy.php b/app/code/Magento/Config/Model/Config/Structure/Search/Proxy.php index eb01cd8615d20..9907fbec18576 100644 --- a/app/code/Magento/Config/Model/Config/Structure/Search/Proxy.php +++ b/app/code/Magento/Config/Model/Config/Structure/Search/Proxy.php @@ -5,7 +5,9 @@ */ namespace Magento\Config\Model\Config\Structure\Search; -class Proxy implements \Magento\Config\Model\Config\Structure\SearchInterface +class Proxy implements + \Magento\Config\Model\Config\Structure\SearchInterface, + \Magento\Framework\ObjectManager\NoninterceptableInterface { /** * Object manager diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceProxy.php.sample b/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceProxy.php.sample index 5ee9c95448ef8..9074f2a8e0926 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceProxy.php.sample +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceProxy.php.sample @@ -7,7 +7,7 @@ namespace Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace; * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -class Proxy extends \Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace +class Proxy extends \Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace implements \Magento\Framework\ObjectManager\NoninterceptableInterface { /** * Object Manager instance diff --git a/lib/internal/Magento/Framework/App/AreaList/Proxy.php b/lib/internal/Magento/Framework/App/AreaList/Proxy.php index 7f2b0a63dbcd8..e7f39ff8aa3e3 100644 --- a/lib/internal/Magento/Framework/App/AreaList/Proxy.php +++ b/lib/internal/Magento/Framework/App/AreaList/Proxy.php @@ -7,7 +7,8 @@ */ namespace Magento\Framework\App\AreaList; -class Proxy extends \Magento\Framework\App\AreaList +class Proxy extends \Magento\Framework\App\AreaList implements + \Magento\Framework\ObjectManager\NoninterceptableInterface { /** * Object Manager instance diff --git a/lib/internal/Magento/Framework/App/Cache/Proxy.php b/lib/internal/Magento/Framework/App/Cache/Proxy.php index 932d5b0c265c8..2e50e0b5d042f 100644 --- a/lib/internal/Magento/Framework/App/Cache/Proxy.php +++ b/lib/internal/Magento/Framework/App/Cache/Proxy.php @@ -3,15 +3,17 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\Framework\App\Cache; + +use \Magento\Framework\App\CacheInterface; +use \Magento\Framework\ObjectManager\NoninterceptableInterface; /** * System cache proxy model */ -namespace Magento\Framework\App\Cache; - -use Magento\Framework\App\CacheInterface; - -class Proxy implements CacheInterface +class Proxy implements + CacheInterface, + NoninterceptableInterface { /** * @var \Magento\Framework\ObjectManagerInterface diff --git a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php index 50a02c458595a..50056798c85ea 100644 --- a/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php +++ b/lib/internal/Magento/Framework/App/Route/ConfigInterface/Proxy.php @@ -10,7 +10,9 @@ /** * Proxy class for \Magento\Framework\App\ResourceConnection */ -class Proxy implements \Magento\Framework\App\Route\ConfigInterface +class Proxy implements + \Magento\Framework\App\Route\ConfigInterface, + \Magento\Framework\ObjectManager\NoninterceptableInterface { /** * Object Manager instance diff --git a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php index 85abc882c7bb4..480af7b06ac86 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data/Proxy.php @@ -8,7 +8,8 @@ /** * Proxy class for @see \Magento\Framework\DataObject\Copy\Config\Data */ -class Proxy extends \Magento\Framework\DataObject\Copy\Config\Data +class Proxy extends \Magento\Framework\DataObject\Copy\Config\Data implements + \Magento\Framework\ObjectManager\NoninterceptableInterface { /** * Object Manager instance diff --git a/lib/internal/Magento/Framework/Interception/ObjectManager/Config/Developer.php b/lib/internal/Magento/Framework/Interception/ObjectManager/Config/Developer.php index ebe41d0f5b46c..28c68a771cefe 100644 --- a/lib/internal/Magento/Framework/Interception/ObjectManager/Config/Developer.php +++ b/lib/internal/Magento/Framework/Interception/ObjectManager/Config/Developer.php @@ -8,9 +8,31 @@ namespace Magento\Framework\Interception\ObjectManager\Config; use Magento\Framework\Interception\ObjectManager\ConfigInterface; +use Magento\Framework\ObjectManager\DefinitionInterface; +use Magento\Framework\ObjectManager\RelationsInterface; +use Magento\Framework\ObjectManager\InterceptableValidator; class Developer extends \Magento\Framework\ObjectManager\Config\Config implements ConfigInterface { + /** + * @var InterceptableValidator + */ + private $interceptableValidator; + + /** + * @param RelationsInterface $relations + * @param DefinitionInterface $definitions + * @param InterceptableValidator $interceptableValidator + */ + public function __construct( + RelationsInterface $relations = null, + DefinitionInterface $definitions = null, + InterceptableValidator $interceptableValidator = null + ) { + $this->interceptableValidator = $interceptableValidator ?: new InterceptableValidator(); + parent::__construct($relations, $definitions); + } + /** * @var \Magento\Framework\Interception\ConfigInterface */ @@ -36,7 +58,9 @@ public function setInterceptionConfig(\Magento\Framework\Interception\ConfigInte public function getInstanceType($instanceName) { $type = parent::getInstanceType($instanceName); - if ($this->interceptionConfig && $this->interceptionConfig->hasPlugins($instanceName)) { + if ($this->interceptionConfig && $this->interceptionConfig->hasPlugins($instanceName) + && $this->interceptableValidator->validate($instanceName) + ) { return $type . '\\Interceptor'; } return $type; diff --git a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php index 0a705796ad559..a026f2a60c82e 100644 --- a/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php +++ b/lib/internal/Magento/Framework/Mview/Config/Data/Proxy.php @@ -8,7 +8,8 @@ /** * Proxy class for \Magento\Framework\Mview\Config\Data */ -class Proxy extends \Magento\Framework\Mview\Config\Data +class Proxy extends \Magento\Framework\Mview\Config\Data implements + \Magento\Framework\ObjectManager\NoninterceptableInterface { /** * Object Manager instance diff --git a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Proxy.php b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Proxy.php index 82686165132f8..c0f86fa70b2be 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Proxy.php +++ b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Proxy.php @@ -14,6 +14,11 @@ class Proxy extends \Magento\Framework\Code\Generator\EntityAbstract */ const ENTITY_TYPE = 'proxy'; + /** + * Marker interface + */ + const NON_INTERCEPTABLE_INTERFACE = '\Magento\Framework\ObjectManager\NoninterceptableInterface'; + /** * @param string $modelClassName * @return string @@ -131,9 +136,10 @@ protected function _generateCode() $reflection = new \ReflectionClass($typeName); if ($reflection->isInterface()) { - $this->_classGenerator->setImplementedInterfaces([$typeName]); + $this->_classGenerator->setImplementedInterfaces([$typeName, self::NON_INTERCEPTABLE_INTERFACE]); } else { $this->_classGenerator->setExtendedClass($typeName); + $this->_classGenerator->setImplementedInterfaces([self::NON_INTERCEPTABLE_INTERFACE]); } return parent::_generateCode(); } diff --git a/lib/internal/Magento/Framework/ObjectManager/InterceptableValidator.php b/lib/internal/Magento/Framework/ObjectManager/InterceptableValidator.php new file mode 100644 index 0000000000000..bc3c17e11d765 --- /dev/null +++ b/lib/internal/Magento/Framework/ObjectManager/InterceptableValidator.php @@ -0,0 +1,59 @@ +isInterceptor($className) && $this->isInterceptable($className); + } + + /** + * + * Check if instance type is interceptor + * + * @param string $instanceName + * @return bool + */ + private function isInterceptor($instanceName) + { + return $this->endsWith($instanceName, '\Interceptor'); + } + + /** + * + * Check if instance type is interceptable + * + * @param string $instanceName + * @return bool + */ + private function isInterceptable($instanceName) + { + return !is_subclass_of( + $instanceName, + \Magento\Framework\ObjectManager\Code\Generator\Proxy::NON_INTERCEPTABLE_INTERFACE + ); + } + + /** + * Check if a string ends with a substring + * + * @param string $haystack + * @param string $needle + * @return bool + */ + private function endsWith($haystack, $needle) + { + // Search forward starting from end minus needle length characters + $temp = strlen($haystack) - strlen($needle); + return $needle === '' || ($temp >= 0 && strpos($haystack, $needle, $temp) !== false); + } +} diff --git a/lib/internal/Magento/Framework/ObjectManager/NoninterceptableInterface.php b/lib/internal/Magento/Framework/ObjectManager/NoninterceptableInterface.php new file mode 100644 index 0000000000000..0950e27c233ce --- /dev/null +++ b/lib/internal/Magento/Framework/ObjectManager/NoninterceptableInterface.php @@ -0,0 +1,13 @@ +assertFalse( + $interceptableValidator->validate( + 'Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper\Interceptor' + ) + ); + $this->assertFalse( + $interceptableValidator->validate( + 'Magento\Test\Di\Proxy' + ) + ); + } +} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/Proxy.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/Proxy.php new file mode 100644 index 0000000000000..864c00098e9e4 --- /dev/null +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/Proxy.php @@ -0,0 +1,10 @@ +getList($path); } } - $inheritanceScanner = new Scanner\InheritanceInterceptorScanner(); + $inheritanceScanner = new Scanner\InheritanceInterceptorScanner( + new \Magento\Framework\ObjectManager\InterceptableValidator() + ); $this->entities['interceptors'] = $inheritanceScanner->collectEntities( get_declared_classes(), $this->entities['interceptors'] diff --git a/setup/src/Magento/Setup/Module/Di/Code/Generator/InterceptionConfigurationBuilder.php b/setup/src/Magento/Setup/Module/Di/Code/Generator/InterceptionConfigurationBuilder.php index 5935e77fa8e71..e929ca2e04a25 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Generator/InterceptionConfigurationBuilder.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Generator/InterceptionConfigurationBuilder.php @@ -12,6 +12,7 @@ use Magento\Framework\App\Interception\Cache\CompiledConfig; use Magento\Framework\Interception\Config\Config as InterceptionConfig; use Magento\Setup\Module\Di\Code\Reader\Type; +use Magento\Framework\ObjectManager\InterceptableValidator; class InterceptionConfigurationBuilder { @@ -42,22 +43,30 @@ class InterceptionConfigurationBuilder */ private $cacheManager; + /** + * @var InterceptableValidator + */ + private $interceptableValidator; + /** * @param InterceptionConfig $interceptionConfig * @param PluginList $pluginList * @param Type $typeReader * @param Manager $cacheManager + * @param InterceptableValidator $interceptableValidator */ public function __construct( InterceptionConfig $interceptionConfig, PluginList $pluginList, Type $typeReader, - Manager $cacheManager + Manager $cacheManager, + InterceptableValidator $interceptableValidator ) { $this->interceptionConfig = $interceptionConfig; $this->pluginList = $pluginList; $this->typeReader = $typeReader; $this->cacheManager = $cacheManager; + $this->interceptableValidator = $interceptableValidator; } /** @@ -99,7 +108,9 @@ private function getInterceptedClasses($definedClasses) { $intercepted = []; foreach ($definedClasses as $definedClass) { - if ($this->interceptionConfig->hasPlugins($definedClass) && $this->typeReader->isConcrete($definedClass)) { + if ($this->interceptionConfig->hasPlugins($definedClass) && $this->typeReader->isConcrete($definedClass) + && $this->interceptableValidator->validate($definedClass) + ) { $intercepted[] = $definedClass; } } diff --git a/setup/src/Magento/Setup/Module/Di/Code/Scanner/InheritanceInterceptorScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Scanner/InheritanceInterceptorScanner.php index 39904e2e20802..733ee606fecf2 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Scanner/InheritanceInterceptorScanner.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Scanner/InheritanceInterceptorScanner.php @@ -5,8 +5,23 @@ */ namespace Magento\Setup\Module\Di\Code\Scanner; +use Magento\Framework\ObjectManager\InterceptableValidator; + class InheritanceInterceptorScanner implements ScannerInterface { + /** + * @var InterceptableValidator + */ + private $interceptableValidator; + + /** + * @param InterceptableValidator $interceptableValidator + */ + public function __construct(InterceptableValidator $interceptableValidator) + { + $this->interceptableValidator = $interceptableValidator; + } + /** * Get intercepted class names * @@ -20,9 +35,7 @@ public function collectEntities(array $classes, array $interceptedEntities = []) foreach ($classes as $class) { foreach ($interceptedEntities as $interceptorClass) { $interceptedEntity = substr($interceptorClass, 0, -12); - if (is_subclass_of($class, $interceptedEntity) - && !$this->endsWith($class, 'RepositoryInterface\\Proxy') - && !$this->endsWith($class, '\\Interceptor')) { + if (is_subclass_of($class, $interceptedEntity) && $this->interceptableValidator->validate($class)) { $reflectionClass = new \ReflectionClass($class); if (!$reflectionClass->isAbstract() && !$reflectionClass->isFinal()) { $output[] = $class . '\\Interceptor'; @@ -53,18 +66,4 @@ private function filterOutAbstractClasses($interceptedEntities) } return $interceptedEntitiesFiltered; } - - /** - * Check if a string ends with a substring - * - * @param string $haystack - * @param string $needle - * @return bool - */ - private function endsWith($haystack, $needle) - { - // search forward starting from end minus needle length characters - return $needle === "" - || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== false); - } } diff --git a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Generator/InterceptionConfigurationBuilderTest.php b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Generator/InterceptionConfigurationBuilderTest.php index 928afe76a0685..1c41ccd774018 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Generator/InterceptionConfigurationBuilderTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Generator/InterceptionConfigurationBuilderTest.php @@ -33,6 +33,11 @@ class InterceptionConfigurationBuilderTest extends \PHPUnit_Framework_TestCase */ private $cacheManager; + /** + * @var \Magento\Framework\ObjectManager\InterceptableValidator|\PHPUnit_Framework_MockObject_MockObject + */ + private $interceptableValidator; + protected function setUp() { $this->interceptionConfig = $this->getMock( @@ -56,13 +61,21 @@ protected function setUp() '', false ); + $this->interceptableValidator = $this->getMock( + 'Magento\Framework\ObjectManager\InterceptableValidator', + [], + [], + '', + false + ); $this->typeReader = $this->getMock('Magento\Setup\Module\Di\Code\Reader\Type', ['isConcrete'], [], '', false); $this->model = new \Magento\Setup\Module\Di\Code\Generator\InterceptionConfigurationBuilder( $this->interceptionConfig, $this->pluginList, $this->typeReader, - $this->cacheManager + $this->cacheManager, + $this->interceptableValidator ); } @@ -82,6 +95,11 @@ public function testGetInterceptionConfiguration($plugins) ['Class1', true], ['instance', true], ]); + $this->interceptableValidator->expects($this->any()) + ->method('validate') + ->with('Class1') + ->willReturn(true); + $this->cacheManager->expects($this->once()) ->method('setEnabled') ->with([CompiledConfig::TYPE_IDENTIFIER], true); From 1ccbe8352e7b52f20873c6c49ccf7b988e17308a Mon Sep 17 00:00:00 2001 From: Hayder Sharhan Date: Thu, 17 Dec 2015 16:03:36 -0600 Subject: [PATCH 02/23] MAGETWO-45728: Travis CI Builds Fail Due to Authentication to repo.magento.com - Took out all occurrences of repo.magento.com in composer.json test files. Conflicts: lib/internal/Magento/Framework/App/Test/Unit/_files/test.composer.json --- .../Composer/_files/testFromCreateProject/composer.json | 8 +------- .../Framework/Composer/_files/testSkeleton/composer.json | 6 ------ .../Magento/Setup/Model/_files/testSkeleton/composer.json | 6 ------ 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.json b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.json index 55c5e6591f085..53009187a595a 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.json +++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.json @@ -39,11 +39,5 @@ } }, "minimum-stability": "alpha", - "prefer-stable": true, - "repositories": [ - { - "type": "composer", - "url": "https://repo.magento.com/" - } - ] + "prefer-stable": true } diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.json b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.json index a8f4e398d2609..2625b60abff4f 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.json +++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.json @@ -4,12 +4,6 @@ "magento/product-community-edition": "0.74.0-beta2", "magento/sample-module-minimal" : "*" }, - "repositories": [ - { - "type": "composer", - "url": "https://repo.magento.com/" - } - ], "autoload": { "psr-4": { "Magento\\Framework\\": "htdocs/lib/internal/Magento/Framework/", diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.json b/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.json index a8f4e398d2609..2625b60abff4f 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.json +++ b/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.json @@ -4,12 +4,6 @@ "magento/product-community-edition": "0.74.0-beta2", "magento/sample-module-minimal" : "*" }, - "repositories": [ - { - "type": "composer", - "url": "https://repo.magento.com/" - } - ], "autoload": { "psr-4": { "Magento\\Framework\\": "htdocs/lib/internal/Magento/Framework/", From 20d353d337cdcc8773bfec996c36f700e7d8fef2 Mon Sep 17 00:00:00 2001 From: Andrii Kasian Date: Fri, 27 Nov 2015 16:17:10 +0200 Subject: [PATCH 03/23] MAGETWO-45882: "Custom option" prices are not present in "Configurable product" order calculations --- .../Model/Product/Type/Configurable/Price.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Price.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Price.php index 4fd0c2c81acf7..2d272f27e25e6 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Price.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Price.php @@ -22,16 +22,16 @@ public function getFinalPrice($qty, $product) return $product->getCalculatedFinalPrice(); } if ($product->getCustomOption('simple_product') && $product->getCustomOption('simple_product')->getProduct()) { - return parent::getFinalPrice($qty, $product->getCustomOption('simple_product')->getProduct()); + $finalPrice = parent::getFinalPrice($qty, $product->getCustomOption('simple_product')->getProduct()); } else { $priceInfo = $product->getPriceInfo(); $finalPrice = $priceInfo->getPrice('final_price')->getAmount()->getValue(); - $finalPrice = $this->_applyOptionsPrice($product, $qty, $finalPrice); - $finalPrice = max(0, $finalPrice); - $product->setFinalPrice($finalPrice); - - return $finalPrice; } + $finalPrice = $this->_applyOptionsPrice($product, $qty, $finalPrice); + $finalPrice = max(0, $finalPrice); + $product->setFinalPrice($finalPrice); + + return $finalPrice; } /** From f5ec1f572d4c3dcf40400705423e8ac8eef6af21 Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Thu, 10 Dec 2015 14:19:44 +0200 Subject: [PATCH 04/23] MAGETWO-46663: Most of category fields dont have Use Default Value option in Store/StoreView scope --- .../Magento/Catalog/Block/Adminhtml/Category/Tab/Attributes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Attributes.php b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Attributes.php index 06a77c8af6023..f73dda6152d1f 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Attributes.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Category/Tab/Attributes.php @@ -11,7 +11,7 @@ */ namespace Magento\Catalog\Block\Adminhtml\Category\Tab; -class Attributes extends \Magento\Backend\Block\Widget\Form\Generic +class Attributes extends \Magento\Catalog\Block\Adminhtml\Form { /** * Retrieve Category object From 91b73d5d45b78b28d2542ea7104be456f66cb180 Mon Sep 17 00:00:00 2001 From: Ievgen Sentiabov Date: Thu, 10 Dec 2015 17:19:51 +0200 Subject: [PATCH 05/23] MAGETWO-46664: Composer Based EE failure on braintree package - Updated version of composer package --- app/code/Magento/Braintree/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Braintree/composer.json b/app/code/Magento/Braintree/composer.json index 5b835db6ad5da..2778dc6dc6bd9 100644 --- a/app/code/Magento/Braintree/composer.json +++ b/app/code/Magento/Braintree/composer.json @@ -16,7 +16,7 @@ "magento/module-directory": "100.0.*", "magento/module-theme": "100.0.*", "magento/framework": "100.0.*", - "braintree/braintree_php": "2.39.0" + "braintree/braintree_php": "3.7.0" }, "suggest": { "magento/module-checkout-agreements": "100.0.*" From e88177a7947c59acfc2004ef1379cb282a8dace2 Mon Sep 17 00:00:00 2001 From: Robert He Date: Wed, 16 Dec 2015 15:19:02 -0600 Subject: [PATCH 06/23] MAGETWO-46808: [GITHUB] Admin order creation fails when "Include Tax In Order Total" set to yes #2675 -- fixed undefined tax index when on backend order page when tax_amount is 0 --- .../templates/order/create/totals/tax.phtml | 4 ++++ .../Magento/Tax/Model/Sales/Total/Quote/Tax.php | 16 +++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) mode change 100644 => 100755 app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml mode change 100644 => 100755 app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml old mode 100644 new mode 100755 index 3f156e6ceaa73..090800ded9969 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals/tax.phtml @@ -6,7 +6,9 @@ // @codingStandardsIgnoreFile +$taxAmount = $block->getTotal()->getValue(); ?> +helper('Magento\Tax\Helper\Data')->displayZeroTax()) || ($taxAmount > 0)): ?> helper('Magento\Tax\Helper\Data')->displayFullSummary()): ?> @@ -50,3 +52,5 @@ formatPrice($block->getTotal()->getValue()) ?> + + diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php old mode 100644 new mode 100755 index 34562754e0893..3a742c4e4ecfa --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php @@ -311,15 +311,13 @@ public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Qu $area = 'taxes'; } - if ($amount != 0 || $this->_config->displayCartZeroTax($store)) { - $totals[] = [ - 'code' => $this->getCode(), - 'title' => __('Tax'), - 'full_info' => $applied ? $applied : [], - 'value' => $amount, - 'area' => $area, - ]; - } + $totals[] = [ + 'code' => $this->getCode(), + 'title' => __('Tax'), + 'full_info' => $applied ? $applied : [], + 'value' => $amount, + 'area' => $area, + ]; /** * Modify subtotal From 1ac556bbe961290ec031416440ee5bb75489e9ee Mon Sep 17 00:00:00 2001 From: Yu Tang Date: Mon, 11 Jan 2016 15:34:09 -0600 Subject: [PATCH 07/23] MAGETWO-46808: [GITHUB] Admin order creation fails when "Include Tax In Order Total" set to yes #2675 - Fixed the case when applied_taxes is in serialized form --- app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php index 3a742c4e4ecfa..19fbc9747f161 100755 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php @@ -299,6 +299,9 @@ public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Qu $totals = []; $store = $quote->getStore(); $applied = $total->getAppliedTaxes(); + if (is_string($applied)) { + $applied = unserialize($applied); + } $amount = $total->getTaxAmount(); if ($amount == null) { $this->enhanceTotalData($quote, $total); From b6974cb82e8d21662f871659751407b76267962f Mon Sep 17 00:00:00 2001 From: Yu Tang Date: Tue, 12 Jan 2016 11:25:58 -0600 Subject: [PATCH 08/23] MAGETWO-46808: [GITHUB] Admin order creation fails when "Include Tax In Order Total" set to yes #2675 - Fix another case where serialized form is expected --- .../Model/Quote/GrandTotalDetailsPlugin.php | 6 +- .../Quote/GrandTotalDetailsPluginTest.php | 211 ++++++++++++++++++ 2 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php diff --git a/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php index 9f52085e7d839..7dca048111242 100644 --- a/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php +++ b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php @@ -94,7 +94,11 @@ public function aroundProcess( $detailsId = 1; $finalData = []; - foreach (unserialize($taxes['full_info']) as $info) { + $fullInfo = $taxes['full_info']; + if (is_string($fullInfo)) { + $fullInfo = unserialize($fullInfo); + } + foreach ($fullInfo as $info) { if ((array_key_exists('hidden', $info) && $info['hidden']) || ($info['amount'] == 0 && $this->taxConfig->displayCartZeroTax()) ) { diff --git a/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php b/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php new file mode 100644 index 0000000000000..2904ade5ccec9 --- /dev/null +++ b/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php @@ -0,0 +1,211 @@ +subjectMock = $this->getMockBuilder('\Magento\Quote\Model\Cart\TotalsConverter') + ->disableOriginalConstructor() + ->getMock(); + + $this->totalSegmentExtensionFactoryMock = $this->getMockBuilder( + '\Magento\Quote\Api\Data\TotalSegmentExtensionFactory' + )->disableOriginalConstructor() + ->getMock(); + + $this->detailsFactoryMock = $this->getMockBuilder('\Magento\Tax\Api\Data\GrandTotalDetailsInterfaceFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->ratesFactoryMock = $this->getMockBuilder('\Magento\Tax\Api\Data\GrandTotalRatesInterfaceFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->taxConfigMock = $this->getMockBuilder('\Magento\Tax\Model\Config') + ->disableOriginalConstructor() + ->getMock(); + + $this->objectManagerHelper = new ObjectManager($this); + $this->model = $this->objectManagerHelper->getObject( + '\Magento\Tax\Model\Quote\GrandTotalDetailsPlugin', + [ + 'totalSegmentExtensionFactory' => $this->totalSegmentExtensionFactoryMock, + 'ratesFactory' => $this->ratesFactoryMock, + 'detailsFactory' => $this->detailsFactoryMock, + 'taxConfig' => $this->taxConfigMock, + ] + ); + } + + protected function setupTaxTotal(array $data) + { + $taxTotalMock = $this->getMockBuilder('\Magento\Quote\Model\Quote\Address\Total') + ->disableOriginalConstructor() + ->getMock(); + + $taxTotalMock->expects($this->any()) + ->method('getData') + ->willReturn($data); + + return $taxTotalMock; + } + + protected function setupTaxRateFactoryMock(array $taxRate) + { + $taxRateMock = $this->getMockBuilder('\Magento\Tax\Api\Data\GrandTotalRatesInterface') + ->getMock(); + + $this->ratesFactoryMock->expects($this->once()) + ->method('create') + ->with([]) + ->willReturn($taxRateMock); + + $taxRateMock->expects($this->once()) + ->method('setPercent') + ->with($taxRate['percent']) + ->willReturnSelf(); + $taxRateMock->expects($this->once()) + ->method('setTitle') + ->with($taxRate['title']) + ->willReturnSelf(); + return $taxRateMock; + } + + protected function setupTaxDetails(array $taxDetails) + { + $taxDetailsMock = $this->getMockBuilder('\Magento\Tax\Api\Data\GrandTotalDetailsInterface') + ->getMock(); + + $this->detailsFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($taxDetailsMock); + + $taxDetailsMock->expects($this->once()) + ->method('setAmount') + ->with($taxDetails['amount']) + ->willReturnSelf(); + + $taxDetailsMock->expects($this->once()) + ->method('setRates') + ->with($taxDetails['rates']) + ->willReturnSelf(); + + $taxDetailsMock->expects($this->once()) + ->method('setGroupId') + ->with(1) + ->willReturnSelf(); + + return $taxDetailsMock; + } + + public function testAroundProcess() + { + $taxRate = [ + 'percent' => 8.25, + 'title' => 'TX', + ]; + $taxAmount = 10; + + + $taxRateMock = $this->setupTaxRateFactoryMock($taxRate); + + $taxDetailsMock = $this->setupTaxDetails( + [ + 'amount' => $taxAmount, + 'rates' => [$taxRateMock], + ] + ); + + $taxTotalData = [ + 'full_info' => [ + [ + 'amount' => $taxAmount, + 'rates' => [$taxRate], + ], + ], + ]; + $taxTotalMock = $this->setupTaxTotal($taxTotalData); + $addressTotals = [ + 'tax' => $taxTotalMock, + ]; + + $extensionAttributeMock = $this->getMockBuilder( + '\Magento\Quote\Api\Data\TotalSegmentExtensionInterface' + )->getMock(); + $extensionAttributeMock->expects($this->once()) + ->method('setTaxGrandtotalDetails') + ->with([$taxDetailsMock]) + ->willReturnSelf(); + + + $taxSegmentMock = $this->getMockBuilder('\Magento\Quote\Model\Cart\TotalSegment') + ->disableOriginalConstructor() + ->getMock(); + $taxSegmentMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($extensionAttributeMock); + $taxSegmentMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($extensionAttributeMock) + ->willReturnSelf(); + + $totalSegments = [ + 'tax' => $taxSegmentMock, + ]; + + $this->closureMock = function () use ($totalSegments) { + return $totalSegments; + }; + + $result = $this->model->aroundProcess($this->subjectMock, $this->closureMock, $addressTotals); + $this->assertEquals($totalSegments, $result); + } +} From b5c834177ba0c97414a96534b483595fed698f6b Mon Sep 17 00:00:00 2001 From: Yu Tang Date: Tue, 12 Jan 2016 13:07:26 -0600 Subject: [PATCH 09/23] MAGETWO-46808: [GITHUB] Admin order creation fails when "Include Tax In Order Total" set to yes #2675 - Fix unit test failure --- .../Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php | 1 + .../Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php index 7dca048111242..14a0fc425ee9b 100644 --- a/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php +++ b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php @@ -75,6 +75,7 @@ protected function getRatesData($rates) * @param \Magento\Quote\Model\Quote\Address\Total[] $addressTotals * @return \Magento\Quote\Api\Data\TotalSegmentInterface[] * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function aroundProcess( \Magento\Quote\Model\Cart\TotalsConverter $subject, diff --git a/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php b/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php index 2904ade5ccec9..1870806dd4262 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php @@ -179,7 +179,12 @@ public function testAroundProcess() $extensionAttributeMock = $this->getMockBuilder( '\Magento\Quote\Api\Data\TotalSegmentExtensionInterface' - )->getMock(); + )->setMethods( + [ + 'setTaxGrandtotalDetails', + + ] + )->getMockForAbstractClass(); $extensionAttributeMock->expects($this->once()) ->method('setTaxGrandtotalDetails') ->with([$taxDetailsMock]) From bfe4148e3acd455cacdf82e5018f608e352676c1 Mon Sep 17 00:00:00 2001 From: Yaroslav Voronoy Date: Fri, 15 Jan 2016 15:30:48 +0200 Subject: [PATCH 10/23] MAGETWO-46808: [GITHUB] Admin order creation fails when "Include Tax In Order Total" set to yes #2675 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6e1eb16a0df2..944d64d550670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,14 @@ * Fixed a potential vulnerability on checkout page * Fixed an issue with upload empty file to custom option * Fixed an issue with performance on customer edit form + * Fixed an issue plugin incorrect calls when proxy exists + * Fixed an issue when travis CI builds fail due to authentication + * Fixed an issue when custom options calculated incorrect for configurable products + * Fixed an issue with changing category form on store view level + * Updated composer version in braintree package * GitHub requests: * [#2519](https://github.com/magento/magento2/issues/2519) -- Fixed an issue where synonyms don't work with Magento 2.0 + * [#2675](https://github.com/magento/magento2/issues/2675) -- Fixed an issue with admin order creation when config "Include Tax In Order Total" set to yes 2.0.0 ============= From 14b0e9b8900258f56f852ce13d82cb57078e8390 Mon Sep 17 00:00:00 2001 From: Ievgen Sentiabov Date: Tue, 12 Jan 2016 15:39:14 +0200 Subject: [PATCH 11/23] MAGETWO-47504: USPS January 17, 2016 API Changes - Renamed 'Standard Post' service to 'Retail Ground' - Removed 'Priority Mail Express Flat Rate Boxes' service - Removed 'Priority Mail Express Flat Rate Boxes Hold For Pickup' service - Removed 'Priority Mail Express International Flat Rate Boxes' service --- app/code/Magento/Usps/Helper/Data.php | 3 +-- app/code/Magento/Usps/Model/Carrier.php | 21 +++++++------------ app/code/Magento/Usps/Setup/InstallData.php | 2 +- .../Usps/Test/Unit/Helper/DataTest.php | 3 +-- .../_files/success_usps_response_rates.xml | 2 +- app/code/Magento/Usps/i18n/en_US.csv | 5 +---- 6 files changed, 12 insertions(+), 24 deletions(-) diff --git a/app/code/Magento/Usps/Helper/Data.php b/app/code/Magento/Usps/Helper/Data.php index 68a126ceb3e14..24631d5c025c3 100644 --- a/app/code/Magento/Usps/Helper/Data.php +++ b/app/code/Magento/Usps/Helper/Data.php @@ -22,7 +22,7 @@ class Data extends AbstractHelper 'usps_1', // Priority Mail 'usps_2', // Priority Mail Express Hold For Pickup 'usps_3', // Priority Mail Express - 'usps_4', // Standard Post + 'usps_4', // Retail Ground 'usps_6', // Media Mail 'usps_INT_1', // Priority Mail Express International 'usps_INT_2', // Priority Mail International @@ -36,7 +36,6 @@ class Data extends AbstractHelper 'usps_INT_14', // First-Class Mail International Large Envelope 'usps_INT_16', // Priority Mail International Small Flat Rate Box 'usps_INT_20', // Priority Mail International Small Flat Rate Envelope - 'usps_INT_26', // Priority Mail Express International Flat Rate Boxes ]; /** diff --git a/app/code/Magento/Usps/Model/Carrier.php b/app/code/Magento/Usps/Model/Carrier.php index ef722b58a9850..1fdc35eab1393 100644 --- a/app/code/Magento/Usps/Model/Carrier.php +++ b/app/code/Magento/Usps/Model/Carrier.php @@ -614,7 +614,7 @@ public function getCode($type, $code = '') '1' => __('Priority Mail'), '2' => __('Priority Mail Express Hold For Pickup'), '3' => __('Priority Mail Express'), - '4' => __('Standard Post'), + '4' => __('Retail Ground'), '6' => __('Media Mail'), '7' => __('Library Mail'), '13' => __('Priority Mail Express Flat Rate Envelope'), @@ -649,8 +649,6 @@ public function getCode($type, $code = '') '49' => __('Priority Mail Regional Rate Box B'), '50' => __('Priority Mail Regional Rate Box B Hold For Pickup'), '53' => __('First-Class Package Service Hold For Pickup'), - '55' => __('Priority Mail Express Flat Rate Boxes'), - '56' => __('Priority Mail Express Flat Rate Boxes Hold For Pickup'), '57' => __('Priority Mail Express Sunday/Holiday Delivery Flat Rate Boxes'), '58' => __('Priority Mail Regional Rate Box C'), '59' => __('Priority Mail Regional Rate Box C Hold For Pickup'), @@ -682,7 +680,6 @@ public function getCode($type, $code = '') 'INT_23' => __('Priority Mail International Padded Flat Rate Envelope'), 'INT_24' => __('Priority Mail International DVD Flat Rate priced box'), 'INT_25' => __('Priority Mail International Large Video Flat Rate priced box'), - 'INT_26' => __('Priority Mail Express International Flat Rate Boxes'), 'INT_27' => __('Priority Mail Express International Padded Flat Rate Envelope'), ], 'service_to_code' => [ @@ -693,7 +690,7 @@ public function getCode($type, $code = '') '1' => 'Priority', '2' => 'Priority Express', '3' => 'Priority Express', - '4' => 'Standard Post', + '4' => 'Retail Ground', '6' => 'Media', '7' => 'Library', '13' => 'Priority Express', @@ -728,8 +725,6 @@ public function getCode($type, $code = '') '49' => 'Priority', '50' => 'Priority', '53' => 'First Class', - '55' => 'Priority Express', - '56' => 'Priority Express', '57' => 'Priority Express', '58' => 'Priority', '59' => 'Priority', @@ -761,7 +756,6 @@ public function getCode($type, $code = '') 'INT_23' => 'Priority', 'INT_24' => 'Priority', 'INT_25' => 'Priority', - 'INT_26' => 'Priority Express', 'INT_27' => 'Priority Express', ], 'method_to_code' => [ @@ -800,9 +794,7 @@ public function getCode($type, $code = '') 'Priority Mail Small Flat Rate Envelope', 'Priority Mail Small Flat Rate Envelope Hold For Pickup', 'First-Class Package Service Hold For Pickup', - 'Priority Mail Express Flat Rate Boxes', - 'Priority Mail Express Flat Rate Boxes Hold For Pickup', - 'Standard Post', + 'Retail Ground', 'Media Mail', 'First-Class Mail Large Envelope', 'Priority Mail Express Sunday/Holiday Delivery', @@ -894,7 +886,7 @@ public function getCode($type, $code = '') 'method' => [ 'Priority Mail Express', 'Priority Mail', - 'Standard Post', + 'Retail Ground', 'Media Mail', 'Library Mail', 'First-Class Package Service', @@ -917,7 +909,7 @@ public function getCode($type, $code = '') 'method' => [ 'Priority Mail Express', 'Priority Mail', - 'Standard Post', + 'Retail Ground', 'Media Mail', 'Library Mail', ], @@ -1489,7 +1481,8 @@ protected function _formUsSignatureConfirmationShipmentRequest(\Magento\Framewor break; case 'STANDARD': case 'Standard Post': - $serviceType = 'Standard Post'; + case 'Retail Ground': + $serviceType = 'Retail Ground'; break; case 'MEDIA': case 'Media': diff --git a/app/code/Magento/Usps/Setup/InstallData.php b/app/code/Magento/Usps/Setup/InstallData.php index 71385fcbea097..234d036a2ee7f 100644 --- a/app/code/Magento/Usps/Setup/InstallData.php +++ b/app/code/Magento/Usps/Setup/InstallData.php @@ -40,7 +40,7 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface 'First-Class Mail Parcel' => '0_FCP', 'First-Class Mail Package' => '0_FCP', 'Parcel Post' => '4', - 'Standard Post' => '4', + 'Retail Ground' => '4', 'Media Mail' => '6', 'Library Mail' => '7', 'Express Mail' => '3', diff --git a/app/code/Magento/Usps/Test/Unit/Helper/DataTest.php b/app/code/Magento/Usps/Test/Unit/Helper/DataTest.php index dec567c7c188a..d4fb8ffc05457 100644 --- a/app/code/Magento/Usps/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Usps/Test/Unit/Helper/DataTest.php @@ -49,7 +49,7 @@ public function shippingMethodDataProvider() ['usps_1'], // Priority Mail ['usps_2'], // Priority Mail Express Hold For Pickup ['usps_3'], // Priority Mail Express - ['usps_4'], // Standard Post + ['usps_4'], // Retail Ground ['usps_6'], // Media Mail ['usps_INT_1'], // Priority Mail Express International ['usps_INT_2'], // Priority Mail International @@ -63,7 +63,6 @@ public function shippingMethodDataProvider() ['usps_INT_14'], // First-Class Mail International Large Envelope ['usps_INT_16'], // Priority Mail International Small Flat Rate Box ['usps_INT_20'], // Priority Mail International Small Flat Rate Envelope - ['usps_INT_26'] // Priority Mail Express International Flat Rate Boxes ]; } } diff --git a/app/code/Magento/Usps/Test/Unit/Model/_files/success_usps_response_rates.xml b/app/code/Magento/Usps/Test/Unit/Model/_files/success_usps_response_rates.xml index cac9563b6579a..42c640752a355 100644 --- a/app/code/Magento/Usps/Test/Unit/Model/_files/success_usps_response_rates.xml +++ b/app/code/Magento/Usps/Test/Unit/Model/_files/success_usps_response_rates.xml @@ -138,7 +138,7 @@ 5.60 - Standard Post<sup>®</sup> + Retail Ground<sup>®</sup> 8.85 diff --git a/app/code/Magento/Usps/i18n/en_US.csv b/app/code/Magento/Usps/i18n/en_US.csv index 9ae0b37ee41ec..d5043c9f78bbf 100644 --- a/app/code/Magento/Usps/i18n/en_US.csv +++ b/app/code/Magento/Usps/i18n/en_US.csv @@ -28,7 +28,7 @@ Length,Length "Priority Mail","Priority Mail" "Priority Mail Express Hold For Pickup","Priority Mail Express Hold For Pickup" "Priority Mail Express","Priority Mail Express" -"Standard Post","Standard Post" +"Retail Ground","Retail Ground" "Media Mail","Media Mail" "Library Mail","Library Mail" "Priority Mail Express Flat Rate Envelope","Priority Mail Express Flat Rate Envelope" @@ -63,8 +63,6 @@ Length,Length "Priority Mail Regional Rate Box B","Priority Mail Regional Rate Box B" "Priority Mail Regional Rate Box B Hold For Pickup","Priority Mail Regional Rate Box B Hold For Pickup" "First-Class Package Service Hold For Pickup","First-Class Package Service Hold For Pickup" -"Priority Mail Express Flat Rate Boxes","Priority Mail Express Flat Rate Boxes" -"Priority Mail Express Flat Rate Boxes Hold For Pickup","Priority Mail Express Flat Rate Boxes Hold For Pickup" "Priority Mail Express Sunday/Holiday Delivery Flat Rate Boxes","Priority Mail Express Sunday/Holiday Delivery Flat Rate Boxes" "Priority Mail Regional Rate Box C","Priority Mail Regional Rate Box C" "Priority Mail Regional Rate Box C Hold For Pickup","Priority Mail Regional Rate Box C Hold For Pickup" @@ -96,7 +94,6 @@ Length,Length "Priority Mail International Padded Flat Rate Envelope","Priority Mail International Padded Flat Rate Envelope" "Priority Mail International DVD Flat Rate priced box","Priority Mail International DVD Flat Rate priced box" "Priority Mail International Large Video Flat Rate priced box","Priority Mail International Large Video Flat Rate priced box" -"Priority Mail Express International Flat Rate Boxes","Priority Mail Express International Flat Rate Boxes" "Priority Mail Express International Padded Flat Rate Envelope","Priority Mail Express International Padded Flat Rate Envelope" Letter,Letter Flat,Flat From 17286a9131af94c948d4dcc4911599ea08654752 Mon Sep 17 00:00:00 2001 From: Yaroslav Voronoy Date: Sat, 16 Jan 2016 17:28:51 +0200 Subject: [PATCH 12/23] MAGETWO-47504: USPS January 17, 2016 API Changes Conflicts: CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 944d64d550670..496929a747971 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * Fixed a potential vulnerability on checkout page * Fixed an issue with upload empty file to custom option * Fixed an issue with performance on customer edit form + * USPS January 17, 2016 API Changes * Fixed an issue plugin incorrect calls when proxy exists * Fixed an issue when travis CI builds fail due to authentication * Fixed an issue when custom options calculated incorrect for configurable products @@ -19,7 +20,7 @@ * GitHub requests: * [#2519](https://github.com/magento/magento2/issues/2519) -- Fixed an issue where synonyms don't work with Magento 2.0 * [#2675](https://github.com/magento/magento2/issues/2675) -- Fixed an issue with admin order creation when config "Include Tax In Order Total" set to yes - + 2.0.0 ============= * Fixed bugs: From 51947d671ef8c57d8fcb7998697d191572a2201c Mon Sep 17 00:00:00 2001 From: "Partica, Cristian" Date: Tue, 29 Dec 2015 13:00:35 -0600 Subject: [PATCH 13/23] MAGETWO-47440: [GITHUB-2471] Incorrect prices on configurable product page when catalog prices include tax - price was adjusted twice, fixed by getting the non adjusted price because it's being adjusted afterwards --- .../ConfigurableProduct/Pricing/Price/FinalPriceResolver.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/FinalPriceResolver.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/FinalPriceResolver.php index cc3f33a5f302c..e837fac0f1cf9 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/FinalPriceResolver.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/FinalPriceResolver.php @@ -16,7 +16,6 @@ class FinalPriceResolver implements PriceResolverInterface */ public function resolvePrice(\Magento\Framework\Pricing\SaleableInterface $product) { - return $product->getPriceInfo()->getPrice(CatalogFinalPrice::PRICE_CODE) - ->getAmount()->getBaseAmount(); + return $product->getPriceInfo()->getPrice(CatalogFinalPrice::PRICE_CODE)->getValue(); } } From e56510062643d4a2ea5e1778b3f1b8b0c3f25589 Mon Sep 17 00:00:00 2001 From: Michail Slabko Date: Wed, 23 Dec 2015 14:20:44 +0200 Subject: [PATCH 14/23] MAGETWO-47267: URL Rewrites do not work for products accessed via category landing pages --- app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml | 3 --- app/code/Magento/CatalogUrlRewrite/etc/di.xml | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml index bfe126bbae028..ddc0ec22cd390 100644 --- a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml +++ b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml @@ -16,9 +16,6 @@ - - - diff --git a/app/code/Magento/CatalogUrlRewrite/etc/di.xml b/app/code/Magento/CatalogUrlRewrite/etc/di.xml index eab00485dd403..8a8da1c5fb24d 100644 --- a/app/code/Magento/CatalogUrlRewrite/etc/di.xml +++ b/app/code/Magento/CatalogUrlRewrite/etc/di.xml @@ -20,4 +20,7 @@ + + + From f722aef2b3b62fb5017410e5749d93f8df82ad53 Mon Sep 17 00:00:00 2001 From: Yaroslav Voronoy Date: Sun, 17 Jan 2016 16:07:28 +0200 Subject: [PATCH 15/23] MAGETWO-47267: URL Rewrites do not work for products accessed via category landing pages Conflicts: CHANGELOG.md --- CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 496929a747971..d1f4432a37d38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,9 +17,34 @@ * Fixed an issue when custom options calculated incorrect for configurable products * Fixed an issue with changing category form on store view level * Updated composer version in braintree package + * Fixed an issue where URL rewrites works incorrect for sample data + * Fixed an issue with BaseURL in static files + * Fixed an issue where customer custom attribute of 'file' type isn't supported by UI Form Component + * Fixed an issue when bin/magento setup:upgrade does not clear cache properly + * Fixed an issue where MessageBox plugin duplicating logic + * Fixed an issue where unnecessary StoreCookie plugin is executed on each request + * Fixed a potential security issue in input filter + * Fixed an issue where category creation from product page fails if google experiments enabled + * Fixed a potential security issue with frontend captcha + * Fixed a potential security issue with block cache + * Fixed an issue where information about selected country in address is not presented on checkout flow + * Fixed an issue where customer segments prevent page from caching + * Fixed an performance issue related to swatch module + * Fixed an issue where import product with replace behaviour causes an error for multistore + * Fixed an issue with validation of url_key during import + * Fixed an issue with "Learn More" link for Payments Pro goes to Payflow Pro +Tests: + * Fixed an issue with test failure in testGetPackagesForUpdate + * Fixed integration tests related to setup/upgrade functionality + * Fixed an issue where PHP7 Integration test failed + * Fixed an issue with autoload functionality for jmx-generator.php file + * Fixed an issue with legacy tests * GitHub requests: * [#2519](https://github.com/magento/magento2/issues/2519) -- Fixed an issue where synonyms don't work with Magento 2.0 * [#2675](https://github.com/magento/magento2/issues/2675) -- Fixed an issue with admin order creation when config "Include Tax In Order Total" set to yes + * [#2471](https://github.com/magento/magento2/issues/2471) -- Fixed an issue with incorrect prices on configurable product page when catalog prices include tax + * [#2674](https://github.com/magento/magento2/issues/2674) -- Fixed an issue where plugins/interceptors don't work with early stage single instance objects + * [#2888](https://github.com/magento/magento2/issues/2888) -- Fixed an issue where not all files are pre-compiled 2.0.0 ============= From a0ed5ec37da12dcc644009251fe83d0a407237e0 Mon Sep 17 00:00:00 2001 From: Yaroslav Voronoy Date: Sat, 16 Jan 2016 15:37:29 +0200 Subject: [PATCH 16/23] MAGETWO-45594: XSS code still can be saved into database Conflicts: CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1f4432a37d38..f366fcdb852a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ * Fixed a potential vulnerability on checkout page * Fixed an issue with upload empty file to custom option * Fixed an issue with performance on customer edit form + * Fixed an issue where minicart does not clears after completing an order via PayPal + * Fixed an potential XSS vulnerability * USPS January 17, 2016 API Changes * Fixed an issue plugin incorrect calls when proxy exists * Fixed an issue when travis CI builds fail due to authentication From 213f169984758c470f5139398deea4970ebdd24a Mon Sep 17 00:00:00 2001 From: Alexander Makeev Date: Tue, 22 Dec 2015 15:58:17 +0000 Subject: [PATCH 17/23] MAGETWO-45594: XSS code still can be saved into database - Removed html tags - Added check to returnUrl action --- .../Magento/Paypal/Controller/Payflow.php | 2 + .../Paypal/Controller/Payflow/ReturnUrl.php | 46 +++++++++++++++++-- .../Controller/Payflowadvanced/ReturnUrl.php | 10 ++++ app/code/Magento/Paypal/i18n/en_US.csv | 1 + 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Paypal/Controller/Payflow.php b/app/code/Magento/Paypal/Controller/Payflow.php index d4a6be5f4f18d..d475c59cc0092 100644 --- a/app/code/Magento/Paypal/Controller/Payflow.php +++ b/app/code/Magento/Paypal/Controller/Payflow.php @@ -73,6 +73,8 @@ public function __construct( */ protected function _cancelPayment($errorMsg = '') { + $errorMsg = trim(strip_tags($errorMsg)); + $gotoSection = false; $this->_checkoutHelper->cancelCurrentOrder($errorMsg); if ($this->_checkoutSession->restoreQuote()) { diff --git a/app/code/Magento/Paypal/Controller/Payflow/ReturnUrl.php b/app/code/Magento/Paypal/Controller/Payflow/ReturnUrl.php index 1907a07045f39..4318b6b2ed785 100644 --- a/app/code/Magento/Paypal/Controller/Payflow/ReturnUrl.php +++ b/app/code/Magento/Paypal/Controller/Payflow/ReturnUrl.php @@ -7,6 +7,7 @@ namespace Magento\Paypal\Controller\Payflow; use Magento\Paypal\Controller\Payflow; +use Magento\Paypal\Model\Config; use Magento\Sales\Model\Order; class ReturnUrl extends Payflow @@ -19,6 +20,15 @@ class ReturnUrl extends Payflow Order::STATE_COMPLETE, ]; + /** + * Payment method code + * @var string + */ + protected $allowedPaymentMethodCodes = [ + Config::METHOD_PAYFLOWPRO, + Config::METHOD_PAYFLOWLINK + ]; + /** * When a customer return to website from payflow gateway. * @@ -35,16 +45,44 @@ public function execute() $order = $this->_orderFactory->create()->loadByIncrementId($this->_checkoutSession->getLastRealOrderId()); if ($order->getIncrementId()) { - if (in_array($order->getState(), $this->allowedOrderStates)) { + if ($this->checkOrderState($order)) { $redirectBlock->setData('goto_success_page', true); } else { - $gotoSection = $this->_cancelPayment(strval($this->getRequest()->getParam('RESPMSG'))); - $redirectBlock->setData('goto_section', $gotoSection); - $redirectBlock->setData('error_msg', __('Your payment has been declined. Please try again.')); + if ($this->checkPaymentMethod($order)) { + $gotoSection = $this->_cancelPayment(strval($this->getRequest()->getParam('RESPMSG'))); + $redirectBlock->setData('goto_section', $gotoSection); + $redirectBlock->setData('error_msg', __('Your payment has been declined. Please try again.')); + } else { + $redirectBlock->setData('goto_section', false); + $redirectBlock->setData('error_msg', __('Requested payment method does not match with order.')); + } } } } $this->_view->renderLayout(); } + + /** + * Check order state + * + * @param Order $order + * @return bool + */ + protected function checkOrderState(Order $order) + { + return in_array($order->getState(), $this->allowedOrderStates); + } + + /** + * Check requested payment method + * + * @param Order $order + * @return bool + */ + protected function checkPaymentMethod(Order $order) + { + $payment = $order->getPayment(); + return in_array($payment->getMethod(), $this->allowedPaymentMethodCodes); + } } diff --git a/app/code/Magento/Paypal/Controller/Payflowadvanced/ReturnUrl.php b/app/code/Magento/Paypal/Controller/Payflowadvanced/ReturnUrl.php index f65daf805eee4..3f2c4ead5be61 100644 --- a/app/code/Magento/Paypal/Controller/Payflowadvanced/ReturnUrl.php +++ b/app/code/Magento/Paypal/Controller/Payflowadvanced/ReturnUrl.php @@ -6,6 +6,8 @@ */ namespace Magento\Paypal\Controller\Payflowadvanced; +use Magento\Paypal\Model\Config; + class ReturnUrl extends \Magento\Paypal\Controller\Payflow\ReturnUrl { /** @@ -13,4 +15,12 @@ class ReturnUrl extends \Magento\Paypal\Controller\Payflow\ReturnUrl * @var string */ protected $_redirectBlockName = 'payflow.advanced.iframe'; + + /** + * Payment method code + * @var string + */ + protected $allowedPaymentMethodCodes = [ + Config::METHOD_PAYFLOWADVANCED + ]; } diff --git a/app/code/Magento/Paypal/i18n/en_US.csv b/app/code/Magento/Paypal/i18n/en_US.csv index c13c7ac0ce277..a999a5624158c 100644 --- a/app/code/Magento/Paypal/i18n/en_US.csv +++ b/app/code/Magento/Paypal/i18n/en_US.csv @@ -693,3 +693,4 @@ unverified,unverified Eligible,Eligible Ineligible,Inligible "PayPal Express Checkout","PayPal Express Checkout" +"Requested payment method does not match with order.","Requested payment method does not match with order." From 568df20cb8fd77d9243a53a773f411bd1af0416a Mon Sep 17 00:00:00 2001 From: Alexander Makeev Date: Mon, 28 Dec 2015 14:00:14 +0000 Subject: [PATCH 18/23] MAGETWO-45594: XSS code still can be saved into database - Added unit test --- .../Unit/Controller/Payflow/ReturnUrlTest.php | 320 +++++++++++++----- 1 file changed, 240 insertions(+), 80 deletions(-) diff --git a/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php b/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php index 96a45ab4cfb23..ee2a6447effd9 100644 --- a/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php @@ -12,9 +12,15 @@ use Magento\Framework\App\View; use Magento\Framework\View\LayoutInterface; use Magento\Paypal\Controller\Payflow\ReturnUrl; +use Magento\Paypal\Controller\Payflowadvanced\ReturnUrl as PayflowadvancedReturnUrl; use Magento\Paypal\Helper\Checkout; use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Payment; use Psr\Log\LoggerInterface; +use Magento\Paypal\Model\Config; +use Magento\Framework\App\Action\Context; +use Magento\Sales\Model\OrderFactory; +use Magento\Paypal\Model\PayflowlinkFactory; /** * Class ReturnUrlTest @@ -29,7 +35,7 @@ class ReturnUrlTest extends \PHPUnit_Framework_TestCase protected $returnUrl; /** - * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var Context|\PHPUnit_Framework_MockObject_MockObject */ protected $contextMock; @@ -49,12 +55,12 @@ class ReturnUrlTest extends \PHPUnit_Framework_TestCase protected $checkoutSessionMock; /** - * @var \Magento\Sales\Model\OrderFactory|\PHPUnit_Framework_MockObject_MockObject + * @var OrderFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $orderFactoryMock; /** - * @var \Magento\Paypal\Model\PayflowlinkFactory|\PHPUnit_Framework_MockObject_MockObject + * @var PayflowlinkFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $payflowlinkFactoryMock; @@ -83,31 +89,44 @@ class ReturnUrlTest extends \PHPUnit_Framework_TestCase */ protected $orderMock; + /** + * @var Payment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $paymentMock; + + const LAST_REAL_ORDER_ID = '000000001'; + protected function setUp() { - $this->contextMock = $this->getMock('Magento\Framework\App\Action\Context', [], [], '', false); - $this->viewMock = $this->getMock('Magento\Framework\App\ViewInterface'); - $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); - $this->layoutMock = $this->getMock('Magento\Framework\View\LayoutInterface'); + $this->contextMock = $this->getMock(Context::class, [], [], '', false); + $this->viewMock = $this->getMock(ViewInterface::class, ['loadLayout', 'getLayout', 'renderLayout']); + $this->requestMock = $this->getMock(Http::class, ['getParam'], [], '', false); + $this->layoutMock = $this->getMock(LayoutInterface::class); $this->blockMock = $this - ->getMockBuilder('\Magento\Checkout\Block\Onepage\Success') + ->getMockBuilder(Success::class) ->disableOriginalConstructor() ->getMock(); - $this->orderFactoryMock = $this->getMock('\Magento\Sales\Model\OrderFactory', ['create'], [], '', false); - $this->payflowlinkFactoryMock = $this->getMock('\Magento\Paypal\Model\PayflowlinkFactory', [], [], '', false); - $this->helperCheckoutMock = $this->getMock('\Magento\Paypal\Helper\Checkout', [], [], '', false); - $this->loggerMock = $this->getMockForAbstractClass('\Psr\Log\LoggerInterface'); + $this->orderFactoryMock = $this->getMock(OrderFactory::class, ['create'], [], '', false); + $this->payflowlinkFactoryMock = $this->getMock(PayflowlinkFactory::class, [], [], '', false); + $this->helperCheckoutMock = $this->getMock(Checkout::class, ['cancelCurrentOrder'], [], '', false); + $this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class); $this->orderMock = $this - ->getMockBuilder('\Magento\Sales\Model\Order') + ->getMockBuilder(Order::class) + ->disableOriginalConstructor() + ->getMock(); + $this->paymentMock = $this + ->getMockBuilder(Payment::class) ->disableOriginalConstructor() ->getMock(); + $this->orderMock->expects($this->any())->method('getPayment')->will($this->returnValue($this->paymentMock)); + $this->checkoutSessionMock = $this - ->getMockBuilder('\Magento\Checkout\Model\Session') + ->getMockBuilder(Session::class) ->setMethods(['getLastRealOrderId', 'getLastRealOrder', 'restoreQuote']) ->disableOriginalConstructor() ->getMock(); - $this->contextMock->expects($this->once())->method('getView')->will($this->returnValue($this->viewMock)); + $this->contextMock->expects($this->any())->method('getView')->will($this->returnValue($this->viewMock)); $this->contextMock->expects($this->any())->method('getRequest')->will($this->returnValue($this->requestMock)); $this->returnUrl = new ReturnUrl( @@ -123,7 +142,7 @@ protected function setUp() /** * @return array */ - public function testAllowedOrderStateDataProvider() + public function allowedOrderStateDataProvider() { return [ [Order::STATE_PROCESSING], @@ -134,7 +153,7 @@ public function testAllowedOrderStateDataProvider() /** * @return array */ - public function testNotAllowedOrderStateDataProvider() + public function notAllowedOrderStateDataProvider() { return [ [Order::STATE_NEW, false, ''], @@ -154,47 +173,21 @@ public function testNotAllowedOrderStateDataProvider() /** * @param $state - * @dataProvider testAllowedOrderStateDataProvider + * @dataProvider allowedOrderStateDataProvider */ public function testExecuteAllowedOrderState($state) { - $lastRealOrderId = '000000001'; + $this->initLayoutMock(); + $this->initOrderMock(self::LAST_REAL_ORDER_ID, $state); - $this->viewMock - ->expects($this->once()) - ->method('getLayout') - ->will($this->returnValue($this->layoutMock)); - - $this->layoutMock - ->expects($this->once()) - ->method('getBlock') - ->will($this->returnValue($this->blockMock)); + $this->requestMock + ->expects($this->never()) + ->method('getParam'); $this->checkoutSessionMock ->expects($this->exactly(2)) ->method('getLastRealOrderId') - ->will($this->returnValue($lastRealOrderId)); - - $this->orderFactoryMock - ->expects($this->once()) - ->method('create') - ->will($this->returnValue($this->orderMock)); - - $this->orderMock - ->expects($this->once()) - ->method('loadByIncrementId') - ->with($lastRealOrderId) - ->will($this->returnSelf()); - - $this->orderMock - ->expects($this->once()) - ->method('getIncrementId') - ->will($this->returnValue($lastRealOrderId)); - - $this->orderMock - ->expects($this->once()) - ->method('getState') - ->will($this->returnValue($state)); + ->will($this->returnValue(self::LAST_REAL_ORDER_ID)); $this->blockMock ->expects($this->once()) @@ -202,6 +195,10 @@ public function testExecuteAllowedOrderState($state) ->with('goto_success_page', true) ->will($this->returnSelf()); + $this->paymentMock + ->expects($this->never()) + ->method('getMethod'); + $this->returnUrl->execute(); } @@ -209,36 +206,172 @@ public function testExecuteAllowedOrderState($state) * @param $state * @param $restoreQuote * @param $expectedGotoSection - * @dataProvider testNotAllowedOrderStateDataProvider + * @dataProvider notAllowedOrderStateDataProvider */ public function testExecuteNotAllowedOrderState($state, $restoreQuote, $expectedGotoSection) { - $lastRealOrderId = '000000001'; - $this->viewMock + $this->initLayoutMock(); + $this->initOrderMock(self::LAST_REAL_ORDER_ID, $state); + $this->initCheckoutSessionMock(self::LAST_REAL_ORDER_ID, $restoreQuote); + + $this->requestMock ->expects($this->once()) - ->method('getLayout') - ->will($this->returnValue($this->layoutMock)); + ->method('getParam') + ->with('RESPMSG') + ->will($this->returnValue('message')); - $this->layoutMock + $this->blockMock + ->expects($this->at(0)) + ->method('setData') + ->with('goto_section', $expectedGotoSection) + ->will($this->returnSelf()); + + $this->blockMock + ->expects($this->at(1)) + ->method('setData') + ->with('error_msg', __('Your payment has been declined. Please try again.')) + ->will($this->returnSelf()); + + $this->paymentMock ->expects($this->once()) - ->method('getBlock') - ->will($this->returnValue($this->blockMock)); + ->method('getMethod') + ->will($this->returnValue(Config::METHOD_PAYFLOWLINK)); + + $this->returnUrl->execute(); + } + + public function testCheckRejectByPaymentMethod() + { + $this->initLayoutMock(); + $this->initOrderMock(self::LAST_REAL_ORDER_ID, Order::STATE_NEW); + + $this->requestMock + ->expects($this->never()) + ->method('getParam'); $this->checkoutSessionMock ->expects($this->any()) ->method('getLastRealOrderId') - ->will($this->returnValue($lastRealOrderId)); + ->will($this->returnValue(self::LAST_REAL_ORDER_ID)); - $this->checkoutSessionMock - ->expects($this->any()) - ->method('getLastRealOrder') - ->will($this->returnValue($this->orderMock)); + $this->blockMock + ->expects($this->at(0)) + ->method('setData') + ->with('goto_section', false) + ->will($this->returnSelf()); - $this->checkoutSessionMock - ->expects($this->any()) - ->method('restoreQuote') - ->will($this->returnValue($restoreQuote)); + $this->blockMock + ->expects($this->at(1)) + ->method('setData') + ->with('error_msg', __('Requested payment method does not match with order.')) + ->will($this->returnSelf()); + + $this->paymentMock + ->expects($this->once()) + ->method('getMethod') + ->will($this->returnValue('something_else')); + + $this->returnUrl->execute(); + } + + /** + * @return array + */ + public function checkXSSEscapedDataProvider() + { + return [ + ['simple', 'simple'], + ['', 'alert(1)'], + ['
', ''] + ]; + } + + /** + * @param $errorMsg + * @param $errorMsgEscaped + * @dataProvider checkXSSEscapedDataProvider + */ + public function testCheckXSSEscaped($errorMsg, $errorMsgEscaped) + { + $this->initLayoutMock(); + $this->initOrderMock(self::LAST_REAL_ORDER_ID, Order::STATE_NEW); + $this->initCheckoutSessionMock(self::LAST_REAL_ORDER_ID, true); + + $this->requestMock + ->expects($this->once()) + ->method('getParam') + ->with('RESPMSG') + ->will($this->returnValue($errorMsg)); + + $this->helperCheckoutMock + ->expects($this->once()) + ->method('cancelCurrentOrder') + ->with($errorMsgEscaped) + ->will($this->returnValue(self::LAST_REAL_ORDER_ID)); + + $this->blockMock + ->expects($this->at(0)) + ->method('setData') + ->with('goto_section', 'paymentMethod') + ->will($this->returnSelf()); + + $this->blockMock + ->expects($this->at(1)) + ->method('setData') + ->with('error_msg', __('Your payment has been declined. Please try again.')) + ->will($this->returnSelf()); + + $this->paymentMock + ->expects($this->once()) + ->method('getMethod') + ->will($this->returnValue(Config::METHOD_PAYFLOWLINK)); + + $this->returnUrl->execute(); + } + + public function testCheckAdvancedAcceptingByPaymentMethod() + { + $this->initLayoutMock(); + $this->initOrderMock(self::LAST_REAL_ORDER_ID, Order::STATE_NEW); + $this->initCheckoutSessionMock(self::LAST_REAL_ORDER_ID, true); + + $this->requestMock + ->expects($this->once()) + ->method('getParam') + ->with('RESPMSG') + ->will($this->returnValue('message')); + + $this->blockMock + ->expects($this->at(0)) + ->method('setData') + ->with('goto_section', 'paymentMethod') + ->will($this->returnSelf()); + + $this->blockMock + ->expects($this->at(1)) + ->method('setData') + ->with('error_msg', __('Your payment has been declined. Please try again.')) + ->will($this->returnSelf()); + + $this->paymentMock + ->expects($this->once()) + ->method('getMethod') + ->will($this->returnValue(Config::METHOD_PAYFLOWADVANCED)); + + $payflowadvancedReturnUrl = new PayflowadvancedReturnUrl( + $this->contextMock, + $this->checkoutSessionMock, + $this->orderFactoryMock, + $this->payflowlinkFactoryMock, + $this->helperCheckoutMock, + $this->loggerMock + ); + + $payflowadvancedReturnUrl->execute(); + } + private function initOrderMock($orderId, $state) + { $this->orderFactoryMock ->expects($this->any()) ->method('create') @@ -247,31 +380,58 @@ public function testExecuteNotAllowedOrderState($state, $restoreQuote, $expected $this->orderMock ->expects($this->once()) ->method('loadByIncrementId') - ->with($lastRealOrderId) + ->with($orderId) ->will($this->returnSelf()); $this->orderMock ->expects($this->once()) ->method('getIncrementId') - ->will($this->returnValue($lastRealOrderId)); + ->will($this->returnValue($orderId)); $this->orderMock ->expects($this->once()) ->method('getState') ->will($this->returnValue($state)); + } - $this->blockMock - ->expects($this->at(0)) - ->method('setData') - ->with('goto_section', $expectedGotoSection) - ->will($this->returnSelf()); + private function initLayoutMock() + { + $this->viewMock + ->expects($this->once()) + ->method('getLayout') + ->will($this->returnValue($this->layoutMock)); - $this->blockMock - ->expects($this->at(1)) - ->method('setData') - ->with('error_msg', __('Your payment has been declined. Please try again.')) - ->will($this->returnSelf()); + $this->viewMock + ->expects($this->once()) + ->method('loadLayout') + ->willReturnSelf(); - $this->returnUrl->execute(); + $this->viewMock + ->expects($this->once()) + ->method('renderLayout') + ->willReturnSelf(); + + $this->layoutMock + ->expects($this->once()) + ->method('getBlock') + ->will($this->returnValue($this->blockMock)); + } + + private function initCheckoutSessionMock($orderId, $restoreQuote) + { + $this->checkoutSessionMock + ->expects($this->any()) + ->method('getLastRealOrderId') + ->will($this->returnValue($orderId)); + + $this->checkoutSessionMock + ->expects($this->any()) + ->method('getLastRealOrder') + ->will($this->returnValue($this->orderMock)); + + $this->checkoutSessionMock + ->expects($this->any()) + ->method('restoreQuote') + ->will($this->returnValue($restoreQuote)); } } From 8ea35854837850ccfb4bbc55e64da3d0faf98c61 Mon Sep 17 00:00:00 2001 From: Alexander Makeev Date: Tue, 29 Dec 2015 13:41:13 +0000 Subject: [PATCH 19/23] MAGETWO-45594: XSS code still can be saved into database - Added templates for redirect --- .../templates/payflowadvanced/iframe.phtml | 15 +++++++++++++++ .../frontend/templates/payflowlink/iframe.phtml | 15 +++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/iframe.phtml create mode 100644 app/code/Magento/Paypal/view/frontend/templates/payflowlink/iframe.phtml diff --git a/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/iframe.phtml b/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/iframe.phtml new file mode 100644 index 0000000000000..06f7bbe5ce888 --- /dev/null +++ b/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/iframe.phtml @@ -0,0 +1,15 @@ + +
+
escapeHtml(__('Please do not refresh the page until you complete payment.')); ?>
+
+ diff --git a/app/code/Magento/Paypal/view/frontend/templates/payflowlink/iframe.phtml b/app/code/Magento/Paypal/view/frontend/templates/payflowlink/iframe.phtml new file mode 100644 index 0000000000000..06f7bbe5ce888 --- /dev/null +++ b/app/code/Magento/Paypal/view/frontend/templates/payflowlink/iframe.phtml @@ -0,0 +1,15 @@ + +
+
escapeHtml(__('Please do not refresh the page until you complete payment.')); ?>
+
+ From a88c7cf5dec8b81549a2619827cdb160227414ab Mon Sep 17 00:00:00 2001 From: Alexander Makeev Date: Tue, 29 Dec 2015 14:11:57 +0000 Subject: [PATCH 20/23] MAGETWO-45594: XSS code still can be saved into database - Fixed bug in iframe constructor --- app/code/Magento/Paypal/Block/Iframe.php | 2 +- .../templates/payflowadvanced/iframe.phtml | 15 --------------- .../frontend/templates/payflowlink/iframe.phtml | 15 --------------- 3 files changed, 1 insertion(+), 31 deletions(-) delete mode 100644 app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/iframe.phtml delete mode 100644 app/code/Magento/Paypal/view/frontend/templates/payflowlink/iframe.phtml diff --git a/app/code/Magento/Paypal/Block/Iframe.php b/app/code/Magento/Paypal/Block/Iframe.php index 8cbc45586c369..e8438c9cc3fea 100644 --- a/app/code/Magento/Paypal/Block/Iframe.php +++ b/app/code/Magento/Paypal/Block/Iframe.php @@ -89,10 +89,10 @@ public function __construct( $this->_hssHelper = $hssHelper; $this->_orderFactory = $orderFactory; $this->_checkoutSession = $checkoutSession; - parent::__construct($context, $data); $this->_isScopePrivate = true; $this->readFactory = $readFactory; $this->reader = $reader; + parent::__construct($context, $data); } /** diff --git a/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/iframe.phtml b/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/iframe.phtml deleted file mode 100644 index 06f7bbe5ce888..0000000000000 --- a/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/iframe.phtml +++ /dev/null @@ -1,15 +0,0 @@ - -
-
escapeHtml(__('Please do not refresh the page until you complete payment.')); ?>
-
- diff --git a/app/code/Magento/Paypal/view/frontend/templates/payflowlink/iframe.phtml b/app/code/Magento/Paypal/view/frontend/templates/payflowlink/iframe.phtml deleted file mode 100644 index 06f7bbe5ce888..0000000000000 --- a/app/code/Magento/Paypal/view/frontend/templates/payflowlink/iframe.phtml +++ /dev/null @@ -1,15 +0,0 @@ - -
-
escapeHtml(__('Please do not refresh the page until you complete payment.')); ?>
-
- From cc141ac903356aa3d8dc9da1a1bf6eadd26a00da Mon Sep 17 00:00:00 2001 From: "Yushkin, Dmytro" Date: Thu, 14 Jan 2016 12:22:38 +0200 Subject: [PATCH 21/23] MAGETWO-45594: XSS code still can be saved into database - Fix by static tests --- .../Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php b/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php index ee2a6447effd9..19f3623d4fa19 100644 --- a/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php @@ -10,6 +10,7 @@ use Magento\Checkout\Model\Session; use Magento\Framework\App\Http; use Magento\Framework\App\View; +use Magento\Framework\App\ViewInterface; use Magento\Framework\View\LayoutInterface; use Magento\Paypal\Controller\Payflow\ReturnUrl; use Magento\Paypal\Controller\Payflowadvanced\ReturnUrl as PayflowadvancedReturnUrl; @@ -99,7 +100,7 @@ class ReturnUrlTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->contextMock = $this->getMock(Context::class, [], [], '', false); - $this->viewMock = $this->getMock(ViewInterface::class, ['loadLayout', 'getLayout', 'renderLayout']); + $this->viewMock = $this->getMock(ViewInterface::class); $this->requestMock = $this->getMock(Http::class, ['getParam'], [], '', false); $this->layoutMock = $this->getMock(LayoutInterface::class); $this->blockMock = $this From 1bcea1551a1c804b2f45dcf8efd31dd847839b54 Mon Sep 17 00:00:00 2001 From: Ievgen Shakhsuvarov Date: Thu, 19 Nov 2015 16:13:38 +0200 Subject: [PATCH 22/23] MAGETWO-42103: Minicart does not clear after completing an order via Paypal --- app/code/Magento/Paypal/etc/frontend/sections.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Paypal/etc/frontend/sections.xml b/app/code/Magento/Paypal/etc/frontend/sections.xml index 1a298d44576f9..2f4e672303e2d 100644 --- a/app/code/Magento/Paypal/etc/frontend/sections.xml +++ b/app/code/Magento/Paypal/etc/frontend/sections.xml @@ -11,4 +11,8 @@
+ +
+
+ From bc35b71759ad74bcef1293707e581b1de2ba8158 Mon Sep 17 00:00:00 2001 From: Yaroslav Voronoy Date: Sun, 17 Jan 2016 16:56:14 +0200 Subject: [PATCH 23/23] MAGETWO-45594: XSS code still can be saved into database --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f366fcdb852a9..c1cc00631275e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,12 +35,14 @@ * Fixed an issue where import product with replace behaviour causes an error for multistore * Fixed an issue with validation of url_key during import * Fixed an issue with "Learn More" link for Payments Pro goes to Payflow Pro + * Fixed an issue with JS error appears if loading product grid after clean cache and static files Tests: * Fixed an issue with test failure in testGetPackagesForUpdate * Fixed integration tests related to setup/upgrade functionality * Fixed an issue where PHP7 Integration test failed * Fixed an issue with autoload functionality for jmx-generator.php file * Fixed an issue with legacy tests + * Fixed an issues in tests related to PHP7 * GitHub requests: * [#2519](https://github.com/magento/magento2/issues/2519) -- Fixed an issue where synonyms don't work with Magento 2.0 * [#2675](https://github.com/magento/magento2/issues/2675) -- Fixed an issue with admin order creation when config "Include Tax In Order Total" set to yes