diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml index dabe16d4a344a40ef93769cd7700fff2ad0806e4..6dd6d3ea9d992df5b4907094abebd2127827a41a 100644 --- a/app/code/Magento/Backend/etc/adminhtml/system.xml +++ b/app/code/Magento/Backend/etc/adminhtml/system.xml @@ -179,6 +179,10 @@ <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> <comment>Warning! Enabling this feature is not recommended on production environments because it represents a potential security risk.</comment> </field> + <field id="minify_html" translate="label" type="select" sortOrder="25" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Minify Html</label> + <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> + </field> </group> <group id="translate_inline" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Translate Inline</label> diff --git a/app/code/Magento/Backend/etc/config.xml b/app/code/Magento/Backend/etc/config.xml index 0d4c5d7180513828a1fd452c6c17d3847b8910d3..ea2586bae427a78a76e1fe2eb2e36077c8683824 100644 --- a/app/code/Magento/Backend/etc/config.xml +++ b/app/code/Magento/Backend/etc/config.xml @@ -7,6 +7,11 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Store/etc/config.xsd"> <default> + <dev> + <template> + <minify_html>1</minify_html> + </template> + </dev> <system> <media_storage_configuration> <allowed_resources> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml index bcc039467893ee6422bb34cb2a5ab8e326eca45d..930efcfb1c1aa92dc4278cbd19f997529a32d1b7 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml @@ -30,7 +30,7 @@ echo 'validate-one-required-by-name' ?>" id="bundle-option-<?php echo $_option->getId() ?>-<?php echo $_selection->getSelectionId() ?>" type="checkbox" - name="bundle_option[<?php echo $_option->getId() ?>][]"<?php if ($block->isSelected($_selection)) { + name="bundle_option[<?php echo $_option->getId() ?>][<?php echo $_selection ?>]"<?php if ($block->isSelected($_selection)) { echo ' checked="checked"' ?><?php if (!$_selection->isSaleable() && !$_skipSaleableCheck) { echo ' disabled="disabled"' ?> value="<?php echo $_selection->getSelectionId() ?>" diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml index d8b5d461196b9d55fe440083ac160a17315e9652..03922735e0c8ec34f66563eb556920916de57d5b 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml @@ -21,7 +21,7 @@ price="<?php echo $block->getSelectionPrice($_selections[0]) ?>" /> <?php else: ?> <select multiple="multiple" size="5" id="bundle-option-<?php echo $_option->getId() ?>" - name="bundle_option[<?php echo $_option->getId() ?>][]" + name="bundle_option[<?php echo $_option->getId() ?>]" class="bundle-option-<?php echo $_option->getId() ?><?php if ($_option->getRequired()) echo ' required-entry' ?> multiselect change-container-classname" onchange="ProductConfigure.bundleControl.changeSelection(this)"> <?php if(!$_option->getRequired()): ?> diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml index 588184ee564d2d2d381250347d8f9fcce9034e1f..00938f3c70c0f58427e5b1302dc9c77f3ee6ed0c 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/checkbox.phtml @@ -30,7 +30,7 @@ id="bundle-option-<?php echo $_option->getId() ?>-<?php echo $_selection->getSelectionId() ?>" type="checkbox" <?php if ($_option->getRequired()) echo 'data-validate="{\'validate-one-required-by-name\':true}"'?> - name="bundle_option[<?php echo $_option->getId() ?>][]" + name="bundle_option[<?php echo $_option->getId() ?>][<?php echo $_selection->getId() ?>]" <?php if ($block->isSelected($_selection)) echo ' checked="checked"' ?> <?php if (!$_selection->isSaleable()) echo ' disabled="disabled"' ?> value="<?php echo $_selection->getSelectionId() ?>"/> diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml index 81cb30bc6f7cf4e8a5eb0d624c72035809eb0ab5..5c32f9c42a23c300464df14ee8292b203755b8da 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml @@ -24,7 +24,7 @@ <select multiple="multiple" size="5" id="bundle-option-<?php echo $_option->getId() ?>" - name="bundle_option[<?php echo $_option->getId() ?>][]" + name="bundle_option[<?php echo $_option->getId() ?>]" class="bundle-option-<?php echo $_option->getId() ?> multiselect product bundle option change-container-classname" <?php if ($_option->getRequired()) echo 'data-validate={required:true}' ?>> <?php if(!$_option->getRequired()): ?> diff --git a/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml b/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml index c14759cdc910ec6f5c14762f917359f872a5fa86..1865f71cd6b75e56cc0ddb0fa9a979079ca56ea9 100644 --- a/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml +++ b/app/code/Magento/Catalog/view/base/templates/product/price/amount/default.phtml @@ -15,7 +15,7 @@ <?php if ($block->getDisplayLabel()): ?> <span class="price-label"><?php echo $block->getDisplayLabel(); ?></span> <?php endif; ?> - <span<?php if ($block->getPriceId()): ?> id="<?php echo $block->getPriceId() ?>"<?php endif;?> + <span <?php if ($block->getPriceId()): ?> id="<?php echo $block->getPriceId() ?>"<?php endif;?> <?php echo($block->getPriceDisplayLabel()) ? 'data-label="' . $block->getPriceDisplayLabel() . $block->getPriceDisplayInclExclTaxes() . '"' : '' ?> data-price-amount="<?php echo $block->getDisplayValue(); ?>" data-price-type="<?php echo $block->getPriceType(); ?>" diff --git a/app/code/Magento/Checkout/Helper/Data.php b/app/code/Magento/Checkout/Helper/Data.php index b3a064ad8163deff1357c9644694bea307e78900..44f5950b80be6b60230d9b008b56b33a5fab7f73 100644 --- a/app/code/Magento/Checkout/Helper/Data.php +++ b/app/code/Magento/Checkout/Helper/Data.php @@ -278,7 +278,11 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper [ 'reason' => $message, 'checkoutType' => $checkoutType, - 'dateAndTime' => $this->_localeDate->date(), + 'dateAndTime' => $this->_localeDate->formatDateTime( + new \DateTime(), + \IntlDateFormatter::MEDIUM, + \IntlDateFormatter::MEDIUM + ), 'customer' => $checkout->getCustomerFirstname() . ' ' . $checkout->getCustomerLastname(), 'customerEmail' => $checkout->getCustomerEmail(), 'billingAddress' => $checkout->getBillingAddress(), diff --git a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php index bc5499166cd061f17548ab4fe1d1c8833c5f34fa..e844d62b7d840199cd200112a946810c1db01e6d 100644 --- a/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Helper/DataTest.php @@ -123,8 +123,9 @@ class DataTest extends \PHPUnit_Framework_TestCase ); $this->_checkoutSession = $arguments['checkoutSession']; - $localeDate = $arguments['localeDate']; - $localeDate->expects($this->any())->method('date')->will($this->returnValue('Oct 02, 2013')); + $arguments['localeDate']->expects($this->any()) + ->method('formatDateTime') + ->willReturn('Oct 02, 2013'); $this->_transportBuilder = $arguments['transportBuilder']; diff --git a/app/code/Magento/Customer/Controller/Account/CreatePost.php b/app/code/Magento/Customer/Controller/Account/CreatePost.php index 50824c3972cf7036d1d4230229c50cfe155748cb..fcefbfaa9fcd69123926b3b4160742ffc68f58fb 100644 --- a/app/code/Magento/Customer/Controller/Account/CreatePost.php +++ b/app/code/Magento/Customer/Controller/Account/CreatePost.php @@ -1,13 +1,14 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Controller\Account; +use Magento\Customer\Model\Account\Redirect as AccountRedirect; use Magento\Customer\Api\Data\AddressInterface; use Magento\Customer\Model\Url; +use Magento\Framework\Api\DataObjectHelper; use Magento\Framework\App\Action\Context; use Magento\Customer\Model\Session; use Magento\Framework\Controller\Result\RedirectFactory; @@ -28,19 +29,12 @@ use Magento\Framework\Escaper; use Magento\Customer\Model\CustomerExtractor; use Magento\Framework\Exception\StateException; use Magento\Framework\Exception\InputException; -use Magento\Store\Model\ScopeInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CreatePost extends \Magento\Customer\Controller\Account { - /** @var ScopeConfigInterface */ - protected $scopeConfig; - - /** @var StoreManagerInterface */ - protected $storeManager; - /** @var AccountManagementInterface */ protected $accountManagement; @@ -77,10 +71,13 @@ class CreatePost extends \Magento\Customer\Controller\Account /** @var \Magento\Framework\UrlInterface */ protected $urlModel; + /** @var DataObjectHelper */ + protected $dataObjectHelper; + /** - * @var \Magento\Framework\Api\DataObjectHelper + * @var AccountRedirect */ - protected $dataObjectHelper; + private $accountRedirect; /** * @param Context $context @@ -101,7 +98,8 @@ class CreatePost extends \Magento\Customer\Controller\Account * @param Registration $registration * @param Escaper $escaper * @param CustomerExtractor $customerExtractor - * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper + * @param DataObjectHelper $dataObjectHelper + * @param AccountRedirect $accountRedirect * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -124,7 +122,8 @@ class CreatePost extends \Magento\Customer\Controller\Account Registration $registration, Escaper $escaper, CustomerExtractor $customerExtractor, - \Magento\Framework\Api\DataObjectHelper $dataObjectHelper + DataObjectHelper $dataObjectHelper, + AccountRedirect $accountRedirect ) { $this->scopeConfig = $scopeConfig; $this->storeManager = $storeManager; @@ -141,7 +140,13 @@ class CreatePost extends \Magento\Customer\Controller\Account $this->customerExtractor = $customerExtractor; $this->urlModel = $urlFactory->create(); $this->dataObjectHelper = $dataObjectHelper; - parent::__construct($context, $customerSession, $resultRedirectFactory, $resultPageFactory); + $this->accountRedirect = $accountRedirect; + parent::__construct( + $context, + $customerSession, + $resultRedirectFactory, + $resultPageFactory + ); } /** @@ -257,9 +262,8 @@ class CreatePost extends \Magento\Customer\Controller\Account $resultRedirect->setUrl($this->_redirect->success($url)); } else { $this->_getSession()->setCustomerDataAsLoggedIn($customer); - $this->messageManager->addSuccess($this->getSuccessMessage()); - $resultRedirect->setUrl($this->getSuccessRedirect()); + $resultRedirect = $this->accountRedirect->getRedirect(); } return $resultRedirect; } catch (StateException $e) { @@ -329,23 +333,4 @@ class CreatePost extends \Magento\Customer\Controller\Account } return $message; } - - /** - * Retrieve success redirect URL - * - * @return string - */ - protected function getSuccessRedirect() - { - $redirectToDashboard = $this->scopeConfig->isSetFlag( - Url::XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD, - ScopeInterface::SCOPE_STORE - ); - if (!$redirectToDashboard && $this->_getSession()->getBeforeAuthUrl()) { - $successUrl = $this->_getSession()->getBeforeAuthUrl(true); - } else { - $successUrl = $this->urlModel->getUrl('*/*/index', ['_secure' => true]); - } - return $this->_redirect->success($successUrl); - } } diff --git a/app/code/Magento/Customer/Controller/Account/EditPost.php b/app/code/Magento/Customer/Controller/Account/EditPost.php index bf13ee5fcc4ef2c3cc611ef2ec2d4d5aa860e896..a3df334fbf83560dc676ee96e415ff842a88ac30 100644 --- a/app/code/Magento/Customer/Controller/Account/EditPost.php +++ b/app/code/Magento/Customer/Controller/Account/EditPost.php @@ -81,6 +81,9 @@ class EditPost extends \Magento\Customer\Controller\Account $customerId = $this->_getSession()->getCustomerId(); $customer = $this->customerExtractor->extract('customer_account_edit', $this->_request); $customer->setId($customerId); + if ($customer->getAddresses() == null) { + $customer->setAddresses($this->customerRepository->getById($customerId)->getAddresses()); + } if ($this->getRequest()->getParam('change_password')) { $currPass = $this->getRequest()->getPost('current_password'); diff --git a/app/code/Magento/Customer/Controller/Account/LoginPost.php b/app/code/Magento/Customer/Controller/Account/LoginPost.php index acc5eb614bba76d01c15f09c63269b2bd55bc8ea..1f05dff29314ebeca53856b305565dca6619aeb1 100644 --- a/app/code/Magento/Customer/Controller/Account/LoginPost.php +++ b/app/code/Magento/Customer/Controller/Account/LoginPost.php @@ -1,19 +1,16 @@ <?php /** - * * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Controller\Account; +use Magento\Customer\Model\Account\Redirect as AccountRedirect; use Magento\Framework\App\Action\Context; use Magento\Customer\Model\Session; use Magento\Framework\Controller\Result\RedirectFactory; use Magento\Framework\View\Result\PageFactory; -use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Store\Model\StoreManagerInterface; use Magento\Customer\Api\AccountManagementInterface; -use Magento\Framework\Url\DecoderInterface; use Magento\Customer\Model\Url as CustomerUrl; use Magento\Framework\Exception\EmailNotConfirmedException; use Magento\Framework\Exception\AuthenticationException; @@ -24,35 +21,26 @@ use Magento\Framework\Data\Form\FormKey\Validator; */ class LoginPost extends \Magento\Customer\Controller\Account { - /** @var ScopeConfigInterface */ - protected $scopeConfig; - - /** @var StoreManagerInterface */ - protected $storeManager; - /** @var AccountManagementInterface */ protected $customerAccountManagement; - /** @var DecoderInterface */ - protected $urlDecoder; - - /** @var CustomerUrl */ - protected $customerUrl; - /** @var Validator */ protected $formKeyValidator; + /** + * @var AccountRedirect + */ + private $accountRedirect; + /** * @param Context $context * @param Session $customerSession * @param RedirectFactory $resultRedirectFactory * @param PageFactory $resultPageFactory - * @param ScopeConfigInterface $scopeConfig - * @param StoreManagerInterface $storeManager * @param AccountManagementInterface $customerAccountManagement - * @param DecoderInterface $urlDecoder * @param CustomerUrl $customerHelperData - * @param \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator + * @param Validator $formKeyValidator + * @param AccountRedirect $accountRedirect * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -61,76 +49,21 @@ class LoginPost extends \Magento\Customer\Controller\Account Session $customerSession, RedirectFactory $resultRedirectFactory, PageFactory $resultPageFactory, - ScopeConfigInterface $scopeConfig, - StoreManagerInterface $storeManager, AccountManagementInterface $customerAccountManagement, - DecoderInterface $urlDecoder, CustomerUrl $customerHelperData, - Validator $formKeyValidator + Validator $formKeyValidator, + AccountRedirect $accountRedirect ) { - $this->scopeConfig = $scopeConfig; - $this->storeManager = $storeManager; $this->customerAccountManagement = $customerAccountManagement; - $this->urlDecoder = $urlDecoder; $this->customerUrl = $customerHelperData; $this->formKeyValidator = $formKeyValidator; - parent::__construct($context, $customerSession, $resultRedirectFactory, $resultPageFactory); - } - - /** - * Define target URL and redirect customer after logging in - * - * @return \Magento\Framework\Controller\Result\Redirect - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function loginPostRedirect() - { - $lastCustomerId = $this->_getSession()->getLastCustomerId(); - if (isset( - $lastCustomerId - ) && $this->_getSession()->isLoggedIn() && $lastCustomerId != $this->_getSession()->getId() - ) { - $this->_getSession()->unsBeforeAuthUrl()->setLastCustomerId($this->_getSession()->getId()); - } - if (!$this->_getSession()->getBeforeAuthUrl() || - $this->_getSession()->getBeforeAuthUrl() == $this->storeManager->getStore()->getBaseUrl() - ) { - // Set default URL to redirect customer to - $this->_getSession()->setBeforeAuthUrl($this->customerUrl->getAccountUrl()); - // Redirect customer to the last page visited after logging in - if ($this->_getSession()->isLoggedIn()) { - if (!$this->scopeConfig->isSetFlag( - CustomerUrl::XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ) - ) { - $referer = $this->getRequest()->getParam(CustomerUrl::REFERER_QUERY_PARAM_NAME); - if ($referer) { - $referer = $this->urlDecoder->decode($referer); - if ($this->_url->isOwnOriginUrl()) { - $this->_getSession()->setBeforeAuthUrl($referer); - } - } - } elseif ($this->_getSession()->getAfterAuthUrl()) { - $this->_getSession()->setBeforeAuthUrl($this->_getSession()->getAfterAuthUrl(true)); - } - } else { - $this->_getSession()->setBeforeAuthUrl($this->customerUrl->getLoginUrl()); - } - } elseif ($this->_getSession()->getBeforeAuthUrl() == $this->customerUrl->getLogoutUrl()) { - $this->_getSession()->setBeforeAuthUrl($this->customerUrl->getDashboardUrl()); - } else { - if (!$this->_getSession()->getAfterAuthUrl()) { - $this->_getSession()->setAfterAuthUrl($this->_getSession()->getBeforeAuthUrl()); - } - if ($this->_getSession()->isLoggedIn()) { - $this->_getSession()->setBeforeAuthUrl($this->_getSession()->getAfterAuthUrl(true)); - } - } - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ - $resultRedirect = $this->resultRedirectFactory->create(); - $resultRedirect->setUrl($this->_getSession()->getBeforeAuthUrl(true)); - return $resultRedirect; + $this->accountRedirect = $accountRedirect; + parent::__construct( + $context, + $customerSession, + $resultRedirectFactory, + $resultPageFactory + ); } /** @@ -177,6 +110,6 @@ class LoginPost extends \Magento\Customer\Controller\Account } } - return $this->loginPostRedirect(); + return $this->accountRedirect->getRedirect(); } } diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php new file mode 100644 index 0000000000000000000000000000000000000000..e230390fa2a991eaa6e3ff1da7e8a14c34c6fb07 --- /dev/null +++ b/app/code/Magento/Customer/Model/Account/Redirect.php @@ -0,0 +1,199 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Customer\Model\Account; + +use Magento\Customer\Model\Session; +use Magento\Customer\Model\Url as CustomerUrl; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\UrlInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Controller\Result\Redirect as ResultRedirect; +use Magento\Framework\Controller\Result\RedirectFactory; +use Magento\Framework\Url\DecoderInterface; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class Redirect +{ + /** + * @var RequestInterface + */ + protected $request; + + /** + * @var ScopeConfigInterface + */ + protected $scopeConfig; + + /** + * @var StoreManagerInterface + */ + protected $storeManager; + + /** + * @var DecoderInterface + */ + protected $urlDecoder; + + /** + * @var CustomerUrl + */ + protected $customerUrl; + + /** + * @var UrlInterface + */ + protected $url; + + /** + * @var RedirectFactory + */ + protected $resultRedirectFactory; + + /** + * @param RequestInterface $request + * @param Session $customerSession + * @param ScopeConfigInterface $scopeConfig + * @param StoreManagerInterface $storeManager + * @param UrlInterface $url + * @param DecoderInterface $urlDecoder + * @param CustomerUrl $customerUrl + * @param RedirectFactory $resultRedirectFactory + */ + public function __construct( + RequestInterface $request, + Session $customerSession, + ScopeConfigInterface $scopeConfig, + StoreManagerInterface $storeManager, + UrlInterface $url, + DecoderInterface $urlDecoder, + CustomerUrl $customerUrl, + RedirectFactory $resultRedirectFactory + ) { + $this->request = $request; + $this->session = $customerSession; + $this->scopeConfig = $scopeConfig; + $this->storeManager = $storeManager; + $this->url = $url; + $this->urlDecoder = $urlDecoder; + $this->customerUrl = $customerUrl; + $this->resultRedirectFactory = $resultRedirectFactory; + } + + /** + * Retrieve redirect + * + * @return ResultRedirect + */ + public function getRedirect() + { + $this->updateLastCustomerId(); + $this->prepareRedirectUrl(); + + /** @var ResultRedirect $resultRedirect */ + $resultRedirect = $this->resultRedirectFactory->create(); + $resultRedirect->setUrl($this->session->getBeforeAuthUrl(true)); + return $resultRedirect; + } + + /** + * Update last customer id, if required + * + * @return void + */ + protected function updateLastCustomerId() + { + $lastCustomerId = $this->session->getLastCustomerId(); + if (isset($lastCustomerId) + && $this->session->isLoggedIn() + && $lastCustomerId != $this->session->getId() + ) { + $this->session->unsBeforeAuthUrl() + ->setLastCustomerId($this->session->getId()); + } + } + + /** + * Prepare redirect URL + * + * @return void + */ + protected function prepareRedirectUrl() + { + $baseUrl = $this->storeManager->getStore()->getBaseUrl(); + + $url = $this->session->getBeforeAuthUrl(); + if (!$url) { + $url = $baseUrl; + } + + switch ($url) { + case $baseUrl: + if ($this->session->isLoggedIn()) { + $this->processLoggedCustomer(); + } else { + $this->applyRedirect($this->customerUrl->getLoginUrl()); + } + break; + + case $this->customerUrl->getLogoutUrl(): + $this->applyRedirect($this->customerUrl->getDashboardUrl()); + break; + + default: + if (!$this->session->getAfterAuthUrl()) { + $this->session->setAfterAuthUrl($this->session->getBeforeAuthUrl()); + } + if ($this->session->isLoggedIn()) { + $this->applyRedirect($this->session->getAfterAuthUrl(true)); + } + break; + } + } + + /** + * Prepare redirect URL for logged in customer + * + * Redirect customer to the last page visited after logging in. + * + * @return void + */ + protected function processLoggedCustomer() + { + // Set default redirect URL for logged in customer + $this->applyRedirect($this->customerUrl->getAccountUrl()); + + if (!$this->scopeConfig->isSetFlag( + CustomerUrl::XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD, + ScopeInterface::SCOPE_STORE + ) + ) { + $referer = $this->request->getParam(CustomerUrl::REFERER_QUERY_PARAM_NAME); + if ($referer) { + $referer = $this->urlDecoder->decode($referer); + if ($this->url->isOwnOriginUrl()) { + $this->applyRedirect($referer); + } + } + } elseif ($this->session->getAfterAuthUrl()) { + $this->applyRedirect($this->session->getAfterAuthUrl(true)); + } + } + + /** + * Prepare redirect URL + * + * @param string $url + * @return void + */ + private function applyRedirect($url) + { + $this->session->setBeforeAuthUrl($url); + } +} diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index c850e8c5a8e16b1f7a2fd8a7f176099b99b123d0..129f46990118ab34ef0bd442198d93f5a5d325c3 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -1077,7 +1077,7 @@ class AccountManagement implements AccountManagementInterface */ public function sendPasswordResetConfirmationEmail($customer) { - $storeId = $customer->getStoreId(); + $storeId = $this->storeManager->getStore()->getId(); if (!$storeId) { $storeId = $this->getWebsiteStoreId($customer); } diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php new file mode 100644 index 0000000000000000000000000000000000000000..86113cef969df40aa3c6f1f1f1603acca0f148b2 --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/EditPostTest.php @@ -0,0 +1,408 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Customer\Test\Unit\Controller\Account; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class EditPostTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $context; + + /** + * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customerSession; + + /** + * @var \Magento\Framework\Controller\Result\RedirectFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultRedirectFactory; + + /** + * @var \Magento\Framework\View\Result\PageFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultPageFactory; + + /** + * @var \Magento\Customer\Api\AccountManagementInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customerAccountManagement; + + /** + * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customerRepository; + + /** + * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit_Framework_MockObject_MockObject + */ + protected $formKeyValidator; + + /** + * @var \Magento\Customer\Model\CustomerExtractor|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customerExtractor; + + /** + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + */ + protected $redirectResultMock; + + /** + * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $response; + + /** + * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $request; + + /** + * @var \Magento\TestFramework\Helper\ObjectManager|\PHPUnit_Framework_MockObject_MockObject + */ + protected $objectManager; + + /** + * @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customer; + + /** + * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject + */ + protected $messageManager; + + public function setUp() + { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->response = $this->getMock('Magento\Framework\App\ResponseInterface', [], [], '', false); + $this->request = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); + + $this->messageManager = $this->getMock('Magento\Framework\Message\Manager', [], [], '', false); + + $this->context = $this->objectManager->getObject( + 'Magento\Framework\App\Action\Context', + [ + 'request' => $this->request, + 'response' => $this->response, + 'messageManager' => $this->messageManager + ] + ); + + $this->redirectResultMock = $this->getMock('Magento\Framework\Controller\Result\Redirect', [], [], '', false); + $this->customerSession = $this->getMock('Magento\Customer\Model\Session', [], [], '', false); + $this->resultRedirectFactory = $this->getMock( + 'Magento\Framework\Controller\Result\RedirectFactory', + ['create'], + [], + '', + false + ); + $this->resultPageFactory = $this->getMock('Magento\Framework\View\Result\PageFactory', [], [], '', false); + $this->customerAccountManagement = $this->getMockForAbstractClass( + 'Magento\Customer\Api\AccountManagementInterface', + [], + '', + false + ); + $this->customerRepository = $this->getMockForAbstractClass( + 'Magento\Customer\Api\CustomerRepositoryInterface', + [], + '', + false + ); + $this->formKeyValidator = $this->getMock('Magento\Framework\Data\Form\FormKey\Validator', [], [], '', false); + $this->customerExtractor = $this->getMock('Magento\Customer\Model\CustomerExtractor', [], [], '', false); + $this->customer = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\CustomerInterface', + [], + 'dataCustomer', + false + ); + } + + /** + * @return \Magento\Customer\Controller\Account\EditPost + */ + public function getController() + { + return $this->objectManager->getObject( + 'Magento\Customer\Controller\Account\EditPost', + [ + 'context' => $this->context, + 'customerSession' => $this->customerSession, + 'resultRedirectFactory' => $this->resultRedirectFactory, + 'resultPageFactory' => $this->resultPageFactory, + 'customerAccountManagement' => $this->customerAccountManagement, + 'customerRepository' => $this->customerRepository, + 'formKeyValidator' => $this->formKeyValidator, + 'customerExtractor' => $this->customerExtractor + ] + ); + } + + public function testEditPostActionWithInvalidFormKey() + { + $this->resultRedirectFactory + ->expects($this->once()) + ->method('create') + ->willReturn($this->redirectResultMock); + $this->formKeyValidator + ->expects($this->once()) + ->method('validate') + ->willReturn(false); + $this->redirectResultMock + ->expects($this->once()) + ->method('setPath') + ->with('*/*/edit') + ->willReturn('http://test.com/customer/account/edit'); + + $this->assertSame($this->redirectResultMock, $this->getController()->execute()); + } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testEditPostActionWithAuthenticationExceptionWhenTryingChangePassword() + { + $customerId = 24; + $address = $this->getMockForAbstractClass('Magento\Customer\Api\Data\AddressInterface', [], '', false); + $loadedCustomer = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\CustomerInterface', + [], + 'loadedCustomer', + false + ); + + $loadedCustomer + ->expects($this->once()) + ->method('getAddresses') + ->willReturn([$address, $address]); + + $this->resultRedirectFactory + ->expects($this->once()) + ->method('create') + ->willReturn($this->redirectResultMock); + $this->formKeyValidator + ->expects($this->once()) + ->method('validate') + ->willReturn(true); + $this->request + ->expects($this->once()) + ->method('isPost') + ->willReturn(true); + + $this->customerSession + ->expects($this->once()) + ->method('getCustomerId') + ->willReturn($customerId); + $this->customerExtractor + ->expects($this->once()) + ->method('extract') + ->willReturn($this->customer); + $this->customer + ->expects($this->once()) + ->method('setId') + ->with($customerId); + $this->customer + ->expects($this->once()) + ->method('getAddresses') + ->willReturn(null); + $this->customerRepository + ->expects($this->exactly(2)) + ->method('getById') + ->with($customerId) + ->willReturn($loadedCustomer); + $this->customer + ->expects($this->once()) + ->method('setAddresses') + ->with([$address, $address]); + $this->request + ->expects($this->once()) + ->method('getParam') + ->with('change_password') + ->willReturn(true); + + $this->request + ->expects($this->at(2)) + ->method('getPost') + ->with('current_password', null) + ->willReturn(123); + $this->request + ->expects($this->at(3)) + ->method('getPost') + ->with('password', null) + ->willReturn(321); + $this->request + ->expects($this->at(4)) + ->method('getPost') + ->with('password_confirmation', null) + ->willReturn(321); + + $this->customerAccountManagement + ->expects($this->once()) + ->method('changePassword') + ->willThrowException(new \Magento\Framework\Exception\AuthenticationException(__('Error'))); + $this->messageManager + ->expects($this->once()) + ->method('addError') + ->with('Error'); + + $exception = new \Magento\Framework\Exception\InputException(__('Error')); + $this->customerRepository + ->expects($this->once()) + ->method('save') + ->willThrowException($exception); + $this->messageManager + ->expects($this->once()) + ->method('addException') + ->with($exception, 'Invalid input'); + $this->request + ->expects($this->once()) + ->method('getPostValue') + ->willReturn([]); + + $messageCollection = $this->getMock('Magento\Framework\Message\Collection', [], [], '', false); + $messageCollection + ->expects($this->once()) + ->method('getCount') + ->willReturn(3); + $this->messageManager + ->expects($this->once()) + ->method('getMessages') + ->willReturn($messageCollection); + $this->customerSession + ->expects($this->once()) + ->method('__call') + ->with('setCustomerFormData', [[]]); + + $this->redirectResultMock + ->expects($this->once()) + ->method('setPath') + ->with('*/*/edit') + ->willReturn('http://test.com/customer/account/edit'); + + $this->assertSame($this->redirectResultMock, $this->getController()->execute()); + } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testEditPostActionWithoutErrors() + { + $customerId = 24; + $address = $this->getMockForAbstractClass('Magento\Customer\Api\Data\AddressInterface', [], '', false); + $loadedCustomer = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\CustomerInterface', + [], + 'loadedCustomer', + false + ); + + $loadedCustomer + ->expects($this->once()) + ->method('getAddresses') + ->willReturn([$address, $address]); + + $this->resultRedirectFactory + ->expects($this->once()) + ->method('create') + ->willReturn($this->redirectResultMock); + $this->formKeyValidator + ->expects($this->once()) + ->method('validate') + ->willReturn(true); + $this->request + ->expects($this->once()) + ->method('isPost') + ->willReturn(true); + + $this->customerSession + ->expects($this->once()) + ->method('getCustomerId') + ->willReturn($customerId); + $this->customerExtractor + ->expects($this->once()) + ->method('extract') + ->willReturn($this->customer); + $this->customer + ->expects($this->once()) + ->method('setId') + ->with($customerId); + $this->customer + ->expects($this->once()) + ->method('getAddresses') + ->willReturn(null); + $this->customerRepository + ->expects($this->exactly(2)) + ->method('getById') + ->with($customerId) + ->willReturn($loadedCustomer); + $this->customer + ->expects($this->once()) + ->method('setAddresses') + ->with([$address, $address]); + $this->request + ->expects($this->once()) + ->method('getParam') + ->with('change_password') + ->willReturn(true); + + $this->request + ->expects($this->at(2)) + ->method('getPost') + ->with('current_password', null) + ->willReturn(123); + $this->request + ->expects($this->at(3)) + ->method('getPost') + ->with('password', null) + ->willReturn(321); + $this->request + ->expects($this->at(4)) + ->method('getPost') + ->with('password_confirmation', null) + ->willReturn(321); + + $this->customerAccountManagement + ->expects($this->once()) + ->method('changePassword'); + + $this->customerRepository + ->expects($this->once()) + ->method('save'); + + $messageCollection = $this->getMock('Magento\Framework\Message\Collection', [], [], '', false); + $messageCollection + ->expects($this->once()) + ->method('getCount') + ->willReturn(0); + $this->messageManager + ->expects($this->once()) + ->method('getMessages') + ->willReturn($messageCollection); + + $this->messageManager + ->expects($this->once()) + ->method('addSuccess') + ->with('The account information has been saved.'); + + $this->redirectResultMock + ->expects($this->once()) + ->method('setPath') + ->with('customer/account') + ->willReturn('http://test.com/customer/account/edit'); + + $this->assertSame($this->redirectResultMock, $this->getController()->execute()); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php index 6f670e3e8ed8fdec1369ba50a78ef712cdec7713..7837c811df305141807f92c816cc06155298ee00 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Account/LoginPostTest.php @@ -96,6 +96,9 @@ class LoginPostTest extends \PHPUnit_Framework_TestCase */ protected $_formKeyValidator; + /** + * @return void + */ protected function setUp() { $this->request = $this->getMockBuilder('Magento\Framework\App\Request\Http') @@ -170,6 +173,7 @@ class LoginPostTest extends \PHPUnit_Framework_TestCase /** * covers \Magento\Customer\Controller\Account::getAllowedActions + * @return void */ public function testGetAllowedActions() { @@ -182,31 +186,4 @@ class LoginPostTest extends \PHPUnit_Framework_TestCase $method->setAccessible(true); $this->assertEquals($this->openActions, $method->invoke($this->object)); } - - public function testLoginPostActionWhenRefererSetBeforeAuthUrl() - { - $this->_formKeyValidator->expects($this->once())->method('validate')->will($this->returnValue(true)); - $this->customerSession->expects($this->at(0))->method('isLoggedIn')->with()->will($this->returnValue(0)); - $this->customerSession->expects($this->at(4))->method('isLoggedIn')->with()->will($this->returnValue(1)); - $this->request->expects( - $this->once() - )->method( - 'getParam' - )->with( - Url::REFERER_QUERY_PARAM_NAME - )->will( - $this->returnValue('referer') - ); - $this->url->expects($this->once())->method('isOwnOriginUrl')->with(); - - $this->redirectFactoryMock->expects($this->once()) - ->method('create') - ->willReturn($this->redirectResultMock); - - $this->redirectResultMock->expects($this->once()) - ->method('setUrl') - ->willReturnSelf(); - - $this->object->execute(); - } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php new file mode 100644 index 0000000000000000000000000000000000000000..367865649d761cc77fddfdf9675218af3e943e81 --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php @@ -0,0 +1,265 @@ +<?php +/** + * Unit test for Magento\Customer\Test\Unit\Model\Account\Redirect + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +namespace Magento\Customer\Test\Unit\Model\Account; + +use Magento\Customer\Model\Account\Redirect; +use Magento\Customer\Model\Url as CustomerUrl; +use Magento\Store\Model\ScopeInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class RedirectTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Redirect + */ + protected $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\App\RequestInterface + */ + protected $request; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Model\Session + */ + protected $customerSession; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\App\Config\ScopeConfigInterface + */ + protected $scopeConfig; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\StoreManagerInterface + */ + protected $storeManager; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\Store + */ + protected $store; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\UrlInterface + */ + protected $url; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Url\DecoderInterface + */ + protected $urlDecoder; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Model\Url + */ + protected $customerUrl; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Controller\Result\Redirect + */ + protected $resultRedirect; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Controller\Result\RedirectFactory + */ + protected $resultRedirectFactory; + + public function setUp() + { + $this->request = $this->getMockForAbstractClass('Magento\Framework\App\RequestInterface'); + + $this->customerSession = $this->getMockBuilder('Magento\Customer\Model\Session') + ->disableOriginalConstructor() + ->setMethods([ + 'getLastCustomerId', + 'isLoggedIn', + 'getId', + 'setLastCustomerId', + 'unsBeforeAuthUrl', + 'getBeforeAuthUrl', + 'setBeforeAuthUrl', + 'getAfterAuthUrl', + 'setAfterAuthUrl', + ]) + ->getMock(); + + $this->scopeConfig = $this->getMockForAbstractClass('Magento\Framework\App\Config\ScopeConfigInterface'); + + $this->store = $this->getMockBuilder('Magento\Store\Model\Store') + ->disableOriginalConstructor() + ->getMock(); + + $this->storeManager = $this->getMockForAbstractClass('Magento\Store\Model\StoreManagerInterface'); + $this->storeManager->expects($this->once()) + ->method('getStore') + ->willReturn($this->store); + + $this->url = $this->getMockForAbstractClass('Magento\Framework\UrlInterface'); + $this->urlDecoder = $this->getMockForAbstractClass('Magento\Framework\Url\DecoderInterface'); + + $this->customerUrl = $this->getMockBuilder('Magento\Customer\Model\Url') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultRedirect = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultRedirectFactory = $this->getMockBuilder('Magento\Framework\Controller\Result\RedirectFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultRedirectFactory->expects($this->once()) + ->method('create') + ->willReturn($this->resultRedirect); + + $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject( + 'Magento\Customer\Model\Account\Redirect', + [ + 'request' => $this->request, + 'customerSession' => $this->customerSession, + 'scopeConfig' => $this->scopeConfig, + 'storeManager' => $this->storeManager, + 'url' => $this->url, + 'urlDecoder' => $this->urlDecoder, + 'customerUrl' => $this->customerUrl, + 'resultRedirectFactory' => $this->resultRedirectFactory + ] + ); + } + + /** + * @dataProvider getRedirectDataProvider + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function testGetRedirect( + $customerId, + $lastCustomerId, + $referer, + $baseUrl, + $beforeAuthUrl, + $afterAuthUrl, + $accountUrl, + $loginUrl, + $logoutUrl, + $dashboardUrl, + $customerLoggedIn, + $redirectToDashboard + ) { + // Preparations for method updateLastCustomerId() + $this->customerSession->expects($this->once()) + ->method('getLastCustomerId') + ->willReturn($customerId); + $this->customerSession->expects($this->any()) + ->method('isLoggedIn') + ->willReturn($customerLoggedIn); + $this->customerSession->expects($this->any()) + ->method('getId') + ->willReturn($lastCustomerId); + $this->customerSession->expects($this->any()) + ->method('unsBeforeAuthUrl') + ->willReturnSelf(); + $this->customerSession->expects($this->any()) + ->method('setLastCustomerId') + ->with($lastCustomerId) + ->willReturnSelf(); + + // Preparations for method prepareRedirectUrl() + $this->store->expects($this->once()) + ->method('getBaseUrl') + ->willReturn($baseUrl); + + $this->customerSession->expects($this->any()) + ->method('getBeforeAuthUrl') + ->willReturn($beforeAuthUrl); + $this->customerSession->expects($this->any()) + ->method('setBeforeAuthUrl') + ->willReturnSelf(); + $this->customerSession->expects($this->any()) + ->method('getAfterAuthUrl') + ->willReturn($afterAuthUrl); + $this->customerSession->expects($this->any()) + ->method('setAfterAuthUrl') + ->with($beforeAuthUrl) + ->willReturnSelf(); + + $this->customerUrl->expects($this->any()) + ->method('getAccountUrl') + ->willReturn($accountUrl); + $this->customerUrl->expects($this->any()) + ->method('getLoginUrl') + ->willReturn($loginUrl); + $this->customerUrl->expects($this->any()) + ->method('getLogoutUrl') + ->willReturn($logoutUrl); + $this->customerUrl->expects($this->any()) + ->method('DashboardUrl') + ->willReturn($dashboardUrl); + + $this->scopeConfig->expects($this->any()) + ->method('isSetFlag') + ->with(CustomerUrl::XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD, ScopeInterface::SCOPE_STORE) + ->willReturn($redirectToDashboard); + + $this->request->expects($this->any()) + ->method('getParam') + ->with(CustomerUrl::REFERER_QUERY_PARAM_NAME) + ->willReturn($referer); + + $this->urlDecoder->expects($this->any()) + ->method('decode') + ->with($referer) + ->willReturn($referer); + + $this->url->expects($this->any()) + ->method('isOwnOriginUrl') + ->willReturn(true); + + $this->resultRedirect->expects($this->once()) + ->method('setUrl') + ->willReturnSelf(); + + $this->model->getRedirect(); + } + + /** + * @return array + */ + public function getRedirectDataProvider() + { + /** + * Customer ID + * Last customer ID + * Referer + * Base URL + * BeforeAuth URL + * AfterAuth URL + * Account URL + * Login URL + * Logout URL + * Dashboard URL + * Is customer logged in flag + * Redirect to Dashboard flag + */ + return [ + // Loggend In, Redirect by Referer + [1, 2, 'referer', 'base', '', '', 'account', '', '', '', true, false], + // Loggend In, Redirect by AfterAuthUrl + [1, 2, 'referer', 'base', '', 'defined', 'account', '', '', '', true, true], + // Not logged In, Redirect by LoginUrl + [1, 2, 'referer', 'base', '', '', 'account', 'login', '', '', false, true], + // Logout, Redirect to Dashboard + [1, 2, 'referer', 'base', 'logout', '', 'account', 'login', 'logout', 'dashboard', false, true], + // Default redirect + [1, 2, 'referer', 'base', 'defined', '', 'account', 'login', 'logout', 'dashboard', true, true], + ]; + } +} diff --git a/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php b/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php index 2de8eaf41e183af60a117dd093ccc338adaba2a5..98537419a90f346fdf884520c90e00ace48ed54c 100644 --- a/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php +++ b/app/code/Magento/Reports/Model/Resource/Report/AbstractReport.php @@ -398,16 +398,21 @@ abstract class AbstractReport extends \Magento\Framework\Model\Resource\Db\Abstr * @param mixed $from * @param mixed $to * @return array + * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _getTZOffsetTransitions($timezone, $from = null, $to = null) { $tzTransitions = []; try { if (!empty($from)) { - $from = (new \DateTime($from))->getTimestamp(); + $from = $from instanceof \DateTime + ? $from->getTimestamp() + : (new \DateTime($from))->getTimestamp(); } - $to = new \DateTime($to); + $to = $to instanceof \DateTime + ? $to + : new \DateTime($to); $nextPeriod = $this->_getWriteAdapter()->formatDate( $to->format('Y-m-d H:i:s') ); diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php index d160ec1223f6156cbc64109a68eb0e2a3a188c00..7141a1bed3a26f0aaac1b4889f8fd0517df050d0 100644 --- a/app/code/Magento/Sales/Model/AdminOrder/Create.php +++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php @@ -1427,7 +1427,7 @@ class Create extends \Magento\Framework\Object implements \Magento\Checkout\Mode $saveInAddressBook = (int)(!empty($address['save_in_address_book'])); $billingAddress->setData('save_in_address_book', $saveInAddressBook); - if ($this->getShippingAddress()->getSameAsBilling()) { + if (!$this->getQuote()->isVirtual() && $this->getShippingAddress()->getSameAsBilling()) { $shippingAddress = clone $billingAddress; $shippingAddress->setSameAsBilling(true); $shippingAddress->setSaveInAddressBook(false); diff --git a/app/code/Magento/Shipping/Model/Observer.php b/app/code/Magento/Shipping/Model/Observer.php index c218e1d1d3f210b2d8b857ec732c7c254b71aa06..e29359060abb9170593593d4b2b50606c98ffdde 100644 --- a/app/code/Magento/Shipping/Model/Observer.php +++ b/app/code/Magento/Shipping/Model/Observer.php @@ -37,8 +37,8 @@ class Observer public function aggregateSalesReportShipmentData() { $this->_localeResolver->emulate(0); - $currentDate = $this->_coreLocale->date(); - $date = $currentDate->subHour(25); + $currentDate = new \DateTime(); + $date = $currentDate->modify('-25 hours'); $this->_shippingFactory->create()->aggregate($date); $this->_localeResolver->revert(); return $this; diff --git a/app/code/Magento/Ui/view/base/web/js/form.js b/app/code/Magento/Ui/view/base/web/js/form.js index 2fec472c353c64f7fdec3ecfbcbbfd470ee7b7d2..ef54b43da90399b6894c697e2f49cb46795af55a 100644 --- a/app/code/Magento/Ui/view/base/web/js/form.js +++ b/app/code/Magento/Ui/view/base/web/js/form.js @@ -3,20 +3,19 @@ * See COPYING.txt for license details. */ define([ + 'jquery', 'underscore', 'Magento_Ui/js/form/component', 'Magento_Ui/js/lib/spinner', './form/adapter' -], function (_, Component, loader, adapter) { +], function ($, _, Component, loader, adapter) { 'use strict'; - function collectData(selector){ - var items = document.querySelectorAll(selector), + function collectData(selector) { + var data = $(selector).serializeArray(), result = {}; - items = Array.prototype.slice.call(items); - - items.forEach(function(item){ + data.forEach(function (item) { result[item.name] = item.value; }); diff --git a/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js b/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js index ffbdfe4c5fbe3774f1d46d1bce60f63adc317085..733448e77319ba27a2481791aac0217e6846456f 100644 --- a/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js +++ b/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js @@ -11,7 +11,7 @@ define([ $.widget('mage.addToWishlist', { options: { - bundleInfo: '[id^=bundle-option-]:checked', + bundleInfo: 'div.control [name^=bundle_option]:not([name*=qty])', configurableInfo: '.super-attribute-select', groupedInfo: '#super-product-table input', downloadableInfo: '#downloadable-links-list input', @@ -32,18 +32,55 @@ define([ this._on(events); }, _updateWishlistData: function(event) { - var dataToAdd = {}; + var dataToAdd = {}, + dataOrigin = {}; + var self = this; $(event.handleObj.selector).each(function(index, element){ - dataToAdd[$(element).attr('name')] = $(element).val(); + dataOrigin = $.extend({}, dataOrigin, self._getElementData(element, 1)); + if ($(element).is(':checked') || $(element).find(':checked').length) { + dataToAdd = $.extend({}, dataToAdd, self._getElementData(element)); + } }); - var self = this; $('[data-action="add-to-wishlist"]').each(function(index, element) { var params = $(element).data('post'); if (!params) params = {}; + self._removeExcessiveData(params, dataOrigin, dataToAdd); params.data = $.extend({}, params.data, dataToAdd, {'qty': $(self.options.qtyInfo).val()}); $(element).data('post', params); }); + event.stopPropagation(); + }, + _arrayDiffByKeys: function(array1, array2) { + var result = {}; + $.each(array1, function(key, value) { + if (!array2[key]) + result[key] = value; + }); + return result; + }, + _getElementData: function(element, origin) { + var data = {}, + elementName = $(element).attr('name'), + elementValue = $(element).val(); + if (origin && $(element).is('select')) { + elementValue = $(element).find('option'); + } + if ($(element).is('select[multiple]')) { + $.each(elementValue, function(key, option) { + var value = origin ? option.value : option; + data[elementName + '[' + value + ']'] = value; + }); + } else { + data[elementName] = elementValue; + } + return data; + }, + _removeExcessiveData: function(params, dataOrigin, dataToAdd) { + var dataToRemove = this._arrayDiffByKeys(dataOrigin, dataToAdd); + $.each(dataToRemove, function(key, value) { + delete params.data[key]; + }); } }); diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml index 7f2caa27ef07634ab7d1e064a10daf54f17db648..f9e5c43acb695f35c3eca409b1d0c12b6b0bcf0d 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml @@ -39,14 +39,12 @@ </variation> <variation name="AddProductToWishlistEntityTestVariation6" firstConstraint="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" method="test"> <data name="product" xsi:type="string">bundleProduct::bundle_dynamic_product</data> - <data name="issue" xsi:type="string">Bug: MAGETWO-33952</data> <constraint name="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" next="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist"/> <constraint name="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist" next="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" prev="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage"/> <constraint name="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" prev="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist"/> </variation> <variation name="AddProductToWishlistEntityTestVariation7" firstConstraint="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" method="test"> <data name="product" xsi:type="string">bundleProduct::bundle_fixed_product</data> - <data name="issue" xsi:type="string">Bug: MAGETWO-33952</data> <constraint name="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" next="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist"/> <constraint name="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist" next="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" prev="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage"/> <constraint name="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" prev="Magento\Wishlist\Test\Constraint\AssertProductDetailsInWishlist"/> diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index a267e9b299762a901b22dc3fc89715a6c0a6e637..63af5eeb61344361524d256fe3cf6f3fa627fc52 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -152,7 +152,7 @@ class AccountTest extends \Magento\TestFramework\TestCase\AbstractController ->setPostValue('create_address', true); $this->dispatch('customer/account/createPost'); - $this->assertRedirect($this->stringContains('customer/account/index/')); + $this->assertRedirect($this->stringContains('customer/account/')); $this->assertSessionMessages( $this->equalTo(['Thank you for registering with Main Website Store.']), MessageInterface::TYPE_SUCCESS diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotations/Helper.php b/dev/tests/static/framework/Magento/Sniffs/Annotations/Helper.php index 42abd3ab3f48ba49d5308f655fbb91b6b03d686a..e2fb6987724b6f2de342839679c2fafe2c728a8e 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotations/Helper.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotations/Helper.php @@ -496,6 +496,8 @@ class Helper // This block of the if should be removed leaving only the phtml condition when dev/tests is swept. // Skip all dev tests files $shouldFilter = true; + } elseif (preg_match('#(?:/|\\\\)Test(?:/|\\\\)Unit(?:/|\\\\)#', $filename)) { + $shouldFilter = true; } elseif (preg_match('/\\.phtml$/', $filename)) { // Skip all phtml files $shouldFilter = true; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php index e47cc2c1d2d314c6050365aeea5d2b1707bb36d0..e87c6a8441447b1c605e33196aae16c8a1d26b29 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php @@ -1905,7 +1905,7 @@ return [ ['_isVatValidationEnabled', 'Magento\Customer\Controller\Account'], ['_createUrl', 'Magento\Customer\Controller\Account'], ['_extractAddress', 'Magento\Customer\Controller\Account\CreatePost', 'Magento\Customer\Controller\Account\CreatePost::extractAddress'], - ['_loginPostRedirect', 'Magento\Customer\Controller\Account\LoginPost', 'Magento\Customer\Controller\Account\LoginPost::loginPostRedirect'], + ['_loginPostRedirect', 'Magento\Customer\Controller\Account\LoginPost', 'Magento\Customer\Model\Account\Redirect::getRedirect'], ['_getAllowedActions', 'Magento\Customer\Controller\Account', 'Magento\Customer\Controller\Account::getAllowedActions'], ['isRegistrationAllowed', 'Magento\Customer\Controller\Account\CreatePost'], ['isRegistrationAllowed', 'Magento\Invitation\Controller\Customer\Account\CreatePost'], @@ -2105,6 +2105,12 @@ return [ 'Magento\Integration\Helper\Validator', 'Magento\Integration\Model\CredentialsValidator::validate' ], + ['getSuccessRedirect', 'Magento\Customer\Controller\Account\CreatePost'], + [ + 'loginPostRedirect', + 'Magento\Customer\Controller\Account\LoginPost', + 'Magento\Customer\Model\Account\Redirect::getRedirect' + ], ['isReviewOwner', 'Magento\Review\Block\Customer\View'], ['getRegistration', 'Magento\Customer\Block\Form\Login', 'Magento\Customer\Block\Form\Login\Info::getRegistration'], ['getCreateAccountUrl', 'Magento\Customer\Block\Form\Login', 'Magento\Customer\Block\Form\Login\Info::getCreateAccountUrl'], diff --git a/lib/internal/Magento/Framework/Controller/Result/RedirectFactory.php b/lib/internal/Magento/Framework/Controller/Result/RedirectFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..1cfc89004602d9283017ba9e28c954b2950de7a0 --- /dev/null +++ b/lib/internal/Magento/Framework/Controller/Result/RedirectFactory.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Controller\Result; + +use Magento\Framework\ObjectManagerInterface; + +class RedirectFactory +{ + /** + * Object Manager instance + * + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * Instance name to create + * + * @var string + */ + protected $instanceName; + + /** + * @param ObjectManagerInterface $objectManager + * @param string $instanceName + */ + public function __construct( + ObjectManagerInterface $objectManager, + $instanceName = 'Magento\Framework\Controller\Result\Redirect' + ) { + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; + } + + /** + * Create class instance with specified parameters + * + * @param array $data + * @return \Magento\Framework\Controller\Result\Redirect + */ + public function create(array $data = []) + { + return $this->objectManager->create($this->instanceName, $data); + } +} diff --git a/lib/internal/Magento/Framework/Controller/Test/Unit/Result/RedirectFactoryTest.php b/lib/internal/Magento/Framework/Controller/Test/Unit/Result/RedirectFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0fb551e749ac560fefe3ae3c3b4a6c71701d59ed --- /dev/null +++ b/lib/internal/Magento/Framework/Controller/Test/Unit/Result/RedirectFactoryTest.php @@ -0,0 +1,45 @@ +<?php +/** + * Unit test for Magento\Framework\ValidatorFactory + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +namespace Magento\Framework\Controller\Test\Unit\Result; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class RedirectFactoryTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Framework\ValidatorFactory */ + private $model; + + /** @var \Magento\Framework\ObjectManagerInterface | \PHPUnit_Framework_MockObject_MockObject */ + private $objectManagerMock; + + public function setUp() + { + $objectManager = new ObjectManager($this); + $this->objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface'); + $this->model = $objectManager->getObject('Magento\Framework\Controller\Result\RedirectFactory', + ['objectManager' => $this->objectManagerMock] + ); + } + + public function testCreate() + { + $redirect = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + + $this->objectManagerMock->expects($this->once())->method('create') + ->willReturn($redirect); + + $resultRedirect = $this->model->create(); + $this->assertInstanceOf('Magento\Framework\Controller\Result\Redirect', $resultRedirect); + $this->assertSame($redirect, $resultRedirect); + } +} diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index d50cf4fc4f534d79133eb308dc8c579ef07fb7bd..e053ca69564b780066f0d08a358a1d911f253cf8 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -741,4 +741,30 @@ class File implements DriverInterface { return realpath($path); } + + /** + * Return correct path for link + * + * @param string $path + * @return mixed + */ + public function getRealPathSafety($path) + { + if (strpos($path, DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) === false) { + return $path; + } + $pathParts = explode(DIRECTORY_SEPARATOR, $path); + $realPath = []; + foreach ($pathParts as $pathPart) { + if ($pathPart == '.') { + continue; + } + if ($pathPart == '..') { + array_pop($realPath); + continue; + } + $realPath[] = $pathPart; + } + return implode(DIRECTORY_SEPARATOR, $realPath); + } } diff --git a/lib/internal/Magento/Framework/Filesystem/DriverInterface.php b/lib/internal/Magento/Framework/Filesystem/DriverInterface.php index aff29eefba7ce7e5f4892f353d7d2890d5f8a86d..c02447ee8c48f1ff0a0c8a065a023a28b535c79f 100644 --- a/lib/internal/Magento/Framework/Filesystem/DriverInterface.php +++ b/lib/internal/Magento/Framework/Filesystem/DriverInterface.php @@ -349,6 +349,14 @@ interface DriverInterface */ public function getRealPath($path); + /** + * Return correct path for link + * + * @param string $path + * @return mixed + */ + public function getRealPathSafety($path); + /** * @param string $basePath * @param null $path diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php index 2bd6553b4fb725a8b848497acf89c92e646f6c50..ab75ed3fd336a7bbf4a5c9bbe8232828c24fd67d 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php @@ -233,7 +233,7 @@ class Timezone implements TimezoneInterface * @param null $locale * @param null $timezone * @param string|null $pattern - * @return mixed + * @return string */ public function formatDateTime( \DateTimeInterface $date, diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php b/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php index 48bbbc73796dba44f8d925ac6e56a61641363d80..75c865b542a0ab78a4d77870f7de12308b2bdec8 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/TimezoneInterface.php @@ -122,7 +122,7 @@ interface TimezoneInterface * @param null $locale * @param null $timezone * @param string|null $pattern - * @return mixed + * @return string */ public function formatDateTime( \DateTimeInterface $date, diff --git a/lib/internal/Magento/Framework/View/Asset/Config.php b/lib/internal/Magento/Framework/View/Asset/Config.php index c18ffaeebabc07f72010e892213be61aac656ab7..1fa3bbde781383f5873c742fe0c358368fa61f46 100644 --- a/lib/internal/Magento/Framework/View/Asset/Config.php +++ b/lib/internal/Magento/Framework/View/Asset/Config.php @@ -4,11 +4,10 @@ * See COPYING.txt for license details. */ -// @codingStandardsIgnoreFile - namespace Magento\Framework\View\Asset; use Magento\Store\Model\ScopeInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; /** * View asset configuration interface @@ -41,14 +40,19 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface const XML_PATH_JS_BUNDLING = 'dev/js/enable_js_bundling'; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * XML path for HTML minification configuration + */ + const XML_PATH_MINIFICATION_HTML = 'dev/template/minify_html'; + + /** + * @var ScopeConfigInterface */ protected $scopeConfig; /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param ScopeConfigInterface $scopeConfig */ - public function __construct(\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig) + public function __construct(ScopeConfigInterface $scopeConfig) { $this->scopeConfig = $scopeConfig; } @@ -60,7 +64,10 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface */ public function isMergeCssFiles() { - return (bool)$this->scopeConfig->isSetFlag(self::XML_PATH_MERGE_CSS_FILES, ScopeInterface::SCOPE_STORE); + return (bool)$this->scopeConfig->isSetFlag( + self::XML_PATH_MERGE_CSS_FILES, + ScopeInterface::SCOPE_STORE + ); } /** @@ -70,7 +77,10 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface */ public function isBundlingJsFiles() { - return (bool)$this->scopeConfig->isSetFlag(self::XML_PATH_JS_BUNDLING, ScopeInterface::SCOPE_STORE); + return (bool)$this->scopeConfig->isSetFlag( + self::XML_PATH_JS_BUNDLING, + ScopeInterface::SCOPE_STORE + ); } /** @@ -80,7 +90,10 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface */ public function isMergeJsFiles() { - return (bool)$this->scopeConfig->isSetFlag(self::XML_PATH_MERGE_JS_FILES, ScopeInterface::SCOPE_STORE); + return (bool)$this->scopeConfig->isSetFlag( + self::XML_PATH_MERGE_JS_FILES, + ScopeInterface::SCOPE_STORE + ); } /** @@ -110,4 +123,17 @@ class Config implements \Magento\Framework\View\Asset\ConfigInterface ScopeInterface::SCOPE_STORE ); } + + /** + * Check whether minify of HTML is on + * + * @return bool + */ + public function isMinifyHtml() + { + return (bool)$this->scopeConfig->isSetFlag( + self::XML_PATH_MINIFICATION_HTML, + ScopeInterface::SCOPE_STORE + ); + } } diff --git a/lib/internal/Magento/Framework/View/Asset/ConfigInterface.php b/lib/internal/Magento/Framework/View/Asset/ConfigInterface.php index b68e6f5fe54ae2bb36919c1e1c6912da5019243f..f099082ce4442631f9690cca216309906362fe81 100644 --- a/lib/internal/Magento/Framework/View/Asset/ConfigInterface.php +++ b/lib/internal/Magento/Framework/View/Asset/ConfigInterface.php @@ -46,4 +46,11 @@ interface ConfigInterface * @return string */ public function getAssetMinificationAdapter($contentType); + + /** + * Check whether minify of HTML is on + * + * @return bool + */ + public function isMinifyHtml(); } diff --git a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php index 656a021c8039db4e1238fa776ccde87c4a38d898..bbf4bcd58450fe37b4f36b6158e4625463cef3d4 100644 --- a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php +++ b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/TemplateFile.php @@ -7,6 +7,7 @@ namespace Magento\Framework\View\Design\FileResolution\Fallback; use Magento\Framework\App\State; +use Magento\Framework\View\Asset\ConfigInterface; use Magento\Framework\View\Design\ThemeInterface; use Magento\Framework\View\Template\Html\MinifierInterface; @@ -25,18 +26,26 @@ class TemplateFile extends File */ protected $templateMinifier; + /** + * @var ConfigInterface + */ + protected $assetConfig; + /** * @param ResolverInterface $resolver * @param MinifierInterface $templateMinifier * @param State $appState + * @param ConfigInterface $assetConfig */ public function __construct( ResolverInterface $resolver, MinifierInterface $templateMinifier, - State $appState + State $appState, + ConfigInterface $assetConfig ) { $this->appState = $appState; $this->templateMinifier = $templateMinifier; + $this->assetConfig = $assetConfig; parent::__construct($resolver); } @@ -60,16 +69,18 @@ class TemplateFile extends File public function getFile($area, ThemeInterface $themeModel, $file, $module = null) { $template = parent::getFile($area, $themeModel, $file, $module); - switch ($this->appState->getMode()) { - case State::MODE_PRODUCTION: - return $this->templateMinifier->getPathToMinified($template); - break; - case State::MODE_DEFAULT: - return $this->templateMinifier->getMinified($template); - break; - case State::MODE_DEVELOPER: - return $template; - break; + + if ($template && $this->assetConfig->isMinifyHtml()) { + switch ($this->appState->getMode()) { + case State::MODE_PRODUCTION: + return $this->templateMinifier->getPathToMinified($template); + case State::MODE_DEFAULT: + return $this->templateMinifier->getMinified($template); + case State::MODE_DEVELOPER: + default: + return $template; + } } + return $template; } } diff --git a/lib/internal/Magento/Framework/View/Template/Html/Minifier.php b/lib/internal/Magento/Framework/View/Template/Html/Minifier.php index 9af26b5705f77006a2e21bd33b0926c0d09478c5..9c3aba6b4ba08fc6d10bca11a1110256aea45fb9 100644 --- a/lib/internal/Magento/Framework/View/Template/Html/Minifier.php +++ b/lib/internal/Magento/Framework/View/Template/Html/Minifier.php @@ -52,15 +52,26 @@ class Minifier implements MinifierInterface 'label', 'select', 'textarea', + '\?', ]; + /** + * @var Filesystem\Directory\ReadInterface + */ + protected $rootDirectory; + + /** + * @var Filesystem\Directory\WriteInterface + */ + protected $htmlDirectory; + /** * @param Filesystem $filesystem */ public function __construct( Filesystem $filesystem ) { - $this->appDirectory = $filesystem->getDirectoryRead(DirectoryList::APP); + $this->rootDirectory = $filesystem->getDirectoryRead(DirectoryList::ROOT); $this->htmlDirectory = $filesystem->getDirectoryWrite(DirectoryList::TEMPLATE_MINIFICATION_DIR); } @@ -72,7 +83,8 @@ class Minifier implements MinifierInterface */ public function getMinified($file) { - if (!$this->htmlDirectory->isExist($this->appDirectory->getRelativePath($file))) { + $file = $this->htmlDirectory->getDriver()->getRealPathSafety($file); + if (!$this->htmlDirectory->isExist($this->rootDirectory->getRelativePath($file))) { $this->minify($file); } return $this->getPathToMinified($file); @@ -87,7 +99,7 @@ class Minifier implements MinifierInterface public function getPathToMinified($file) { return $this->htmlDirectory->getAbsolutePath( - $this->appDirectory->getRelativePath($file) + $this->rootDirectory->getRelativePath($file) ); } @@ -95,24 +107,33 @@ class Minifier implements MinifierInterface * Minify template file * * @param string $file + * @return void */ public function minify($file) { - $file = $this->appDirectory->getRelativePath($file); + $file = $this->rootDirectory->getRelativePath($file); $content = preg_replace( - '#(?<!' . implode('|', $this->inlineHtmlTags) . ')\> \<#', - '><', + '#(?<!]]>)\s+</#', + '</', preg_replace( - '#(?ix)(?>[^\S ]\s*|\s{2,})(?=(?:(?:[^<]++|<(?!/?(?:textarea|pre|script)\b))*+)' - . '(?:<(?>textarea|pre|script)\b|\z))#', - ' ', + '#((?:<\?php\s+(?!echo)[^\?]*)\?>)\s+#', + '$1', preg_replace( - '#(?<!:)//(?!\<\!\[)(?!]]\>)[^\n\r]*#', - '', + '#(?<!' . implode('|', $this->inlineHtmlTags) . ')\> \<#', + '><', preg_replace( - '#(?<!:)//[^\n\r]*(\s\?\>)#', - '$1', - $this->appDirectory->readFile($file) + '#(?ix)(?>[^\S ]\s*|\s{2,})(?=(?:(?:[^<]++|<(?!/?(?:textarea|pre|script)\b))*+)' + . '(?:<(?>textarea|pre|script)\b|\z))#', + ' ', + preg_replace( + '#(?<!:)//(?!\s*\<\!\[)(?!\s*]]\>)[^\n\r]*#', + '', + preg_replace( + '#(?<!:)//[^\n\r]*(\s\?\>)#', + '$1', + $this->rootDirectory->readFile($file) + ) + ) ) ) ) @@ -121,6 +142,6 @@ class Minifier implements MinifierInterface if (!$this->htmlDirectory->isExist()) { $this->htmlDirectory->create(); } - $this->htmlDirectory->writeFile($file, $content); + $this->htmlDirectory->writeFile($file, rtrim($content)); } } diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php index 644876622074ed95b4da80934857c9c78c15d54a..359ea18c0f08e8c12c94cefbdf212bd14c415b40 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/TemplateFileTest.php @@ -6,10 +6,10 @@ namespace Magento\Framework\View\Test\Unit\Design\FileResolution\Fallback; -use \Magento\Framework\View\Design\FileResolution\Fallback\TemplateFile; - use Magento\Framework\App\State; use Magento\Framework\View\Design\Fallback\RulePool; +use Magento\Framework\View\Design\FileResolution\Fallback\TemplateFile; +use Magento\Framework\View\Design\FileResolution\Fallback\ResolverInterface; class TemplateFileTest extends \PHPUnit_Framework_TestCase { @@ -33,12 +33,23 @@ class TemplateFileTest extends \PHPUnit_Framework_TestCase */ protected $object; + /** + * @var \Magento\Framework\View\Asset\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $assetConfig; + protected function setUp() { $this->resolver = $this->getMock('Magento\Framework\View\Design\FileResolution\Fallback\ResolverInterface'); $this->minifier = $this->getMock('Magento\Framework\View\Template\Html\MinifierInterface'); $this->state = $this->getMockBuilder('Magento\Framework\App\State')->disableOriginalConstructor()->getMock(); - $this->object = new TemplateFile($this->resolver, $this->minifier, $this->state); + $this->assetConfig = $this->getMockForAbstractClass( + 'Magento\Framework\View\Asset\ConfigInterface', + [], + '', + false + ); + $this->object = new TemplateFile($this->resolver, $this->minifier, $this->state, $this->assetConfig); } /** @@ -46,6 +57,11 @@ class TemplateFileTest extends \PHPUnit_Framework_TestCase */ public function testGetFileWhenStateDeveloper() { + $this->assetConfig + ->expects($this->once()) + ->method('isMinifyHtml') + ->willReturn(true); + $theme = $this->getMockForAbstractClass('\Magento\Framework\View\Design\ThemeInterface'); $expected = 'some/file.ext'; @@ -63,10 +79,17 @@ class TemplateFileTest extends \PHPUnit_Framework_TestCase /** * Cover getFile when mode is default + * @param string $mode + * @param string $method * @dataProvider getMinifiedDataProvider */ public function testGetFileWhenModifiedNeeded($mode, $method) { + $this->assetConfig + ->expects($this->once()) + ->method('isMinifyHtml') + ->willReturn(true); + $theme = $this->getMockForAbstractClass('\Magento\Framework\View\Design\ThemeInterface'); $expected = 'some/file.ext'; $expectedMinified = '/path/to/minified/some/file.ext'; @@ -87,6 +110,27 @@ class TemplateFileTest extends \PHPUnit_Framework_TestCase $this->assertSame($expectedMinified, $actual); } + public function testGetFileIfMinificationIsDisabled() + { + $this->assetConfig + ->expects($this->once()) + ->method('isMinifyHtml') + ->willReturn(false); + + $theme = $this->getMockForAbstractClass('\Magento\Framework\View\Design\ThemeInterface'); + $expected = 'some/file.ext'; + + $this->resolver->expects($this->once()) + ->method('resolve') + ->with(RulePool::TYPE_TEMPLATE_FILE, 'file.ext', 'frontend', $theme, null, 'Magento_Module') + ->will($this->returnValue($expected)); + + $this->state->expects($this->never())->method('getMode'); + + $actual = $this->object->getFile('frontend', $theme, 'file.ext', 'Magento_Module'); + $this->assertSame($expected, $actual); + } + /** * Contain different methods by mode for HTML minification * diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php index 20c3d33358cd872d4f0904394478e750283ca990..a93962b3ae7e689f4ef943e5273b9da9afd8cffc 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php @@ -6,9 +6,8 @@ namespace Magento\Framework\View\Test\Unit\Template\Html; -use \Magento\Framework\View\Template\Html\Minifier; - use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\View\Template\Html\Minifier; class MinifierTest extends \PHPUnit_Framework_TestCase { @@ -39,7 +38,7 @@ class MinifierTest extends \PHPUnit_Framework_TestCase $filesystem->expects($this->once()) ->method('getDirectoryRead') - ->with(DirectoryList::APP) + ->with(DirectoryList::ROOT) ->willReturn($this->appDirectory); $filesystem->expects($this->once()) ->method('getDirectoryWrite') @@ -72,6 +71,7 @@ class MinifierTest extends \PHPUnit_Framework_TestCase $this->assertEquals($absolutePath, $this->object->getPathToMinified($file)); } + // @codingStandardsIgnoreStart /** * Covered method minify and test regular expressions * @test @@ -115,8 +115,9 @@ class MinifierTest extends \PHPUnit_Framework_TestCase </body> </html> TEXT; + $expectedContent = <<<TEXT -<?php /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ ?><?php ?><html><head><title>Test title</title></head><body><a href="http://somelink.com/text.html">Text Link</a> <img src="test.png" alt="some text" /><?php echo \$block->someMethod(); ?><div style="width: 800px" class="<?php echo \$block->getClass() ?>" /><script> +<?php /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ ?><?php ?><html><head><title>Test title</title></head><body><a href="http://somelink.com/text.html">Text Link</a> <img src="test.png" alt="some text" /><?php echo \$block->someMethod(); ?> <div style="width: 800px" class="<?php echo \$block->getClass() ?>" /><script> //<![CDATA[ var someVar = 123; testFunctionCall(function () { @@ -128,7 +129,7 @@ TEXT; } }); //]]> - </script><?php echo "http://some.link.com/" ?><em>inline text</em> </body></html> +</script><?php echo "http://some.link.com/" ?> <em>inline text</em></body></html> TEXT; $this->appDirectory->expects($this->once()) @@ -151,6 +152,7 @@ TEXT; $this->object->minify($file); } + // @codingStandardsIgnoreEnd /** * Contain method modify and getPathToModified @@ -161,15 +163,28 @@ TEXT; $file = '/absolute/path/to/phtml/template/file'; $relativePath = 'relative/path/to/phtml/template/file'; - $this->appDirectory->expects($this->at(0)) + $htmlDriver = $this->getMock('Magento\Framework\Filesystem\DriverInterface', [], [], '', false); + $htmlDriver + ->expects($this->once()) + ->method('getRealPathSafety') + ->willReturn($file); + + $this->appDirectory + ->expects($this->exactly(3)) ->method('getRelativePath') ->with($file) ->willReturn($relativePath); - $this->htmlDirectory->expects($this->at(0)) + $this->htmlDirectory + ->expects($this->at(1)) ->method('isExist') ->with($relativePath) ->willReturn(false); + $this->htmlDirectory + ->expects($this->once()) + ->method('getDriver') + ->willReturn($htmlDriver); + $this->object->getMinified($file); } }