diff --git a/CHANGELOG.md b/CHANGELOG.md
index b6e1eb16a0df2..c1cc00631275e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,9 +11,45 @@
* 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
+ * 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
+ * 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
+ * [#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
=============
* Fixed bugs:
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.*"
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
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 @@
+
+
+
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/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;
}
/**
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();
}
}
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/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/Test/Unit/Controller/Payflow/ReturnUrlTest.php b/app/code/Magento/Paypal/Test/Unit/Controller/Payflow/ReturnUrlTest.php
index 96a45ab4cfb23..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,11 +10,18 @@
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;
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 +36,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 +56,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 +90,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);
+ $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 +143,7 @@ protected function setUp()
/**
* @return array
*/
- public function testAllowedOrderStateDataProvider()
+ public function allowedOrderStateDataProvider()
{
return [
[Order::STATE_PROCESSING],
@@ -134,7 +154,7 @@ public function testAllowedOrderStateDataProvider()
/**
* @return array
*/
- public function testNotAllowedOrderStateDataProvider()
+ public function notAllowedOrderStateDataProvider()
{
return [
[Order::STATE_NEW, false, ''],
@@ -154,47 +174,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 +196,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 +207,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 +381,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));
}
}
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 @@
+
+
+
+
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."
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/Quote/GrandTotalDetailsPlugin.php b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php
index 9f52085e7d839..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,
@@ -94,7 +95,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/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..19fbc9747f161
--- 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);
@@ -311,15 +314,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
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..1870806dd4262
--- /dev/null
+++ b/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php
@@ -0,0 +1,216 @@
+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'
+ )->setMethods(
+ [
+ 'setTaxGrandtotalDetails',
+
+ ]
+ )->getMockForAbstractClass();
+ $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);
+ }
+}
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
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/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/",
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);