diff --git a/app/code/Magento/Backend/App/AbstractAction.php b/app/code/Magento/Backend/App/AbstractAction.php index fb2daa283f111..2f01700bdf51c 100644 --- a/app/code/Magento/Backend/App/AbstractAction.php +++ b/app/code/Magento/Backend/App/AbstractAction.php @@ -3,11 +3,26 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Backend\App; +use Magento\Backend\App\Action\Context; +use Magento\Backend\Helper\Data as BackendHelper; +use Magento\Backend\Model\Auth; +use Magento\Backend\Model\Session; +use Magento\Backend\Model\UrlInterface; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\AuthorizationInterface; +use Magento\Framework\Data\Form\FormKey\Validator as FormKeyValidator; +use Magento\Framework\Locale\ResolverInterface; +use Magento\Framework\View\Element\AbstractBlock; + /** * Generic backend controller * + * @deprecated Use \Magento\Framework\App\ActionInterface + * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.NumberOfChildren) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -45,32 +60,32 @@ abstract class AbstractAction extends \Magento\Framework\App\Action\Action protected $_sessionNamespace = self::SESSION_NAMESPACE; /** - * @var \Magento\Backend\Helper\Data + * @var BackendHelper */ protected $_helper; /** - * @var \Magento\Backend\Model\Session + * @var Session */ protected $_session; /** - * @var \Magento\Framework\AuthorizationInterface + * @var AuthorizationInterface */ protected $_authorization; /** - * @var \Magento\Backend\Model\Auth + * @var Auth */ protected $_auth; /** - * @var \Magento\Backend\Model\UrlInterface + * @var UrlInterface */ protected $_backendUrl; /** - * @var \Magento\Framework\Locale\ResolverInterface + * @var ResolverInterface */ protected $_localeResolver; @@ -80,14 +95,14 @@ abstract class AbstractAction extends \Magento\Framework\App\Action\Action protected $_canUseBaseUrl; /** - * @var \Magento\Framework\Data\Form\FormKey\Validator + * @var FormKeyValidator */ protected $_formKeyValidator; /** - * @param \Magento\Backend\App\Action\Context $context + * @param Context $context */ - public function __construct(Action\Context $context) + public function __construct(Context $context) { parent::__construct($context); $this->_authorization = $context->getAuthorization(); @@ -101,6 +116,95 @@ public function __construct(Action\Context $context) } /** + * Dispatches the Action + * + * @param RequestInterface $request + * @return \Magento\Framework\App\ResponseInterface + */ + public function dispatch(RequestInterface $request) + { + if ($request->isDispatched() && $request->getActionName() !== 'denied' && !$this->_isAllowed()) { + $this->_response->setStatusHeader(403, '1.1', 'Forbidden'); + if (!$this->_auth->isLoggedIn()) { + return $this->_redirect('*/auth/login'); + } + + $this->_view->loadLayout(['default', 'adminhtml_denied'], true, true, false); + $this->_view->renderLayout(); + $this->_request->setDispatched(true); + + return $this->_response; + } + + if ($this->_isUrlChecked()) { + $this->_actionFlag->set('', self::FLAG_IS_URLS_CHECKED, true); + } + + $this->_processLocaleSettings(); + + // Need to preload isFirstPageAfterLogin (see https://github.com/magento/magento2/issues/15510) + if ($this->_auth->isLoggedIn()) { + $this->_auth->getAuthStorage()->isFirstPageAfterLogin(); + } + + return parent::dispatch($request); + } + + /** + * Check url keys. If non valid - redirect + * + * @return bool + * + * @see \Magento\Backend\App\Request\BackendValidator for default request validation. + */ + public function _processUrlKeys() + { + $_isValidFormKey = true; + $_isValidSecretKey = true; + $_keyErrorMsg = ''; + if ($this->_auth->isLoggedIn()) { + if ($this->getRequest()->isPost()) { + $_isValidFormKey = $this->_formKeyValidator->validate($this->getRequest()); + $_keyErrorMsg = __('Invalid Form Key. Please refresh the page.'); + } elseif ($this->_backendUrl->useSecretKey()) { + $_isValidSecretKey = $this->_validateSecretKey(); + $_keyErrorMsg = __('You entered an invalid Secret Key. Please refresh the page.'); + } + } + if (!$_isValidFormKey || !$_isValidSecretKey) { + $this->_actionFlag->set('', self::FLAG_NO_DISPATCH, true); + $this->_actionFlag->set('', self::FLAG_NO_POST_DISPATCH, true); + if ($this->getRequest()->getQuery('isAjax', false) || $this->getRequest()->getQuery('ajax', false)) { + $this->getResponse()->representJson( + $this->_objectManager->get( + \Magento\Framework\Json\Helper\Data::class + )->jsonEncode( + ['error' => true, 'message' => $_keyErrorMsg] + ) + ); + } else { + $this->_redirect($this->_backendUrl->getStartupPageUrl()); + } + return false; + } + return true; + } + + /** + * Generate url by route and parameters + * + * @param string $route + * @param array $params + * @return string + */ + public function getUrl($route = '', $params = []) + { + return $this->_helper->getUrl($route, $params); + } + + /** + * Determines whether current user is allowed to access Action + * * @return bool */ protected function _isAllowed() @@ -119,6 +223,8 @@ protected function _getSession() } /** + * Returns instantiated Message\ManagerInterface. + * * @return \Magento\Framework\Message\ManagerInterface */ protected function getMessageManager() @@ -146,6 +252,8 @@ protected function _setActiveMenu($itemId) } /** + * Adds element to Breadcrumbs block + * * @param string $label * @param string $title * @param string|null $link @@ -158,79 +266,51 @@ protected function _addBreadcrumb($label, $title, $link = null) } /** - * @param \Magento\Framework\View\Element\AbstractBlock $block + * Adds block to `content` block + * + * @param AbstractBlock $block * @return $this */ - protected function _addContent(\Magento\Framework\View\Element\AbstractBlock $block) + protected function _addContent(AbstractBlock $block) { return $this->_moveBlockToContainer($block, 'content'); } /** - * @param \Magento\Framework\View\Element\AbstractBlock $block + * Moves Block to `left` container + * + * @param AbstractBlock $block * @return $this */ - protected function _addLeft(\Magento\Framework\View\Element\AbstractBlock $block) + protected function _addLeft(AbstractBlock $block) { return $this->_moveBlockToContainer($block, 'left'); } /** - * @param \Magento\Framework\View\Element\AbstractBlock $block + * Adds Block to `js` container + * + * @param AbstractBlock $block * @return $this */ - protected function _addJs(\Magento\Framework\View\Element\AbstractBlock $block) + protected function _addJs(AbstractBlock $block) { return $this->_moveBlockToContainer($block, 'js'); } /** - * Set specified block as an anonymous child to specified container - * - * The block will be moved to the container from previous parent after all other elements + * Set specified block as an anonymous child to specified container. * - * @param \Magento\Framework\View\Element\AbstractBlock $block + * @param AbstractBlock $block * @param string $containerName * @return $this */ - private function _moveBlockToContainer(\Magento\Framework\View\Element\AbstractBlock $block, $containerName) + private function _moveBlockToContainer(AbstractBlock $block, $containerName) { $this->_view->getLayout()->setChild($containerName, $block->getNameInLayout(), ''); return $this; } - /** - * @param \Magento\Framework\App\RequestInterface $request - * @return \Magento\Framework\App\ResponseInterface - */ - public function dispatch(\Magento\Framework\App\RequestInterface $request) - { - if ($request->isDispatched() && $request->getActionName() !== 'denied' && !$this->_isAllowed()) { - $this->_response->setStatusHeader(403, '1.1', 'Forbidden'); - if (!$this->_auth->isLoggedIn()) { - return $this->_redirect('*/auth/login'); - } - $this->_view->loadLayout(['default', 'adminhtml_denied'], true, true, false); - $this->_view->renderLayout(); - $this->_request->setDispatched(true); - - return $this->_response; - } - - if ($this->_isUrlChecked()) { - $this->_actionFlag->set('', self::FLAG_IS_URLS_CHECKED, true); - } - - $this->_processLocaleSettings(); - - // Need to preload isFirstPageAfterLogin (see https://github.com/magento/magento2/issues/15510) - if ($this->_auth->isLoggedIn()) { - $this->_auth->getAuthStorage()->isFirstPageAfterLogin(); - } - - return parent::dispatch($request); - } - /** * Check whether url is checked * @@ -239,55 +319,13 @@ public function dispatch(\Magento\Framework\App\RequestInterface $request) protected function _isUrlChecked() { return !$this->_actionFlag->get('', self::FLAG_IS_URLS_CHECKED) - && !$this->getRequest()->isForwarded() - && !$this->_getSession()->getIsUrlNotice(true) - && !$this->_canUseBaseUrl; - } - - /** - * Check url keys. If non valid - redirect - * - * @return bool - * - * @see \Magento\Backend\App\Request\BackendValidator for default - * request validation. - */ - public function _processUrlKeys() - { - $_isValidFormKey = true; - $_isValidSecretKey = true; - $_keyErrorMsg = ''; - if ($this->_auth->isLoggedIn()) { - if ($this->getRequest()->isPost()) { - $_isValidFormKey = $this->_formKeyValidator->validate($this->getRequest()); - $_keyErrorMsg = __('Invalid Form Key. Please refresh the page.'); - } elseif ($this->_backendUrl->useSecretKey()) { - $_isValidSecretKey = $this->_validateSecretKey(); - $_keyErrorMsg = __('You entered an invalid Secret Key. Please refresh the page.'); - } - } - if (!$_isValidFormKey || !$_isValidSecretKey) { - $this->_actionFlag->set('', self::FLAG_NO_DISPATCH, true); - $this->_actionFlag->set('', self::FLAG_NO_POST_DISPATCH, true); - if ($this->getRequest()->getQuery('isAjax', false) || $this->getRequest()->getQuery('ajax', false)) { - $this->getResponse()->representJson( - $this->_objectManager->get( - \Magento\Framework\Json\Helper\Data::class - )->jsonEncode( - ['error' => true, 'message' => $_keyErrorMsg] - ) - ); - } else { - $this->_redirect($this->_backendUrl->getStartupPageUrl()); - } - return false; - } - return true; + && !$this->getRequest()->isForwarded() + && !$this->_getSession()->getIsUrlNotice(true) + && !$this->_canUseBaseUrl; } /** - * Set session locale, - * process force locale set through url params + * Set session locale, process force locale set through url params * * @return $this */ @@ -309,8 +347,8 @@ protected function _processLocaleSettings() * Set redirect into response * * @TODO MAGETWO-28356: Refactor controller actions to new ResultInterface - * @param string $path - * @param array $arguments + * @param string $path + * @param array $arguments * @return \Magento\Framework\App\ResponseInterface */ protected function _redirect($path, $arguments = []) @@ -333,19 +371,7 @@ protected function _redirect($path, $arguments = []) protected function _forward($action, $controller = null, $module = null, array $params = null) { $this->_getSession()->setIsUrlNotice($this->_actionFlag->get('', self::FLAG_IS_URLS_CHECKED)); - return parent::_forward($action, $controller, $module, $params); - } - - /** - * Generate url by route and parameters - * - * @param string $route - * @param array $params - * @return string - */ - public function getUrl($route = '', $params = []) - { - return $this->_helper->getUrl($route, $params); + parent::_forward($action, $controller, $module, $params); } /** @@ -359,7 +385,7 @@ protected function _validateSecretKey() return true; } - $secretKey = $this->getRequest()->getParam(\Magento\Backend\Model\UrlInterface::SECRET_KEY_PARAM_NAME, null); + $secretKey = $this->getRequest()->getParam(UrlInterface::SECRET_KEY_PARAM_NAME, null); if (!$secretKey || $secretKey != $this->_backendUrl->getSecretKey()) { return false; } diff --git a/app/code/Magento/Backend/App/Action/Plugin/LoadDesignPlugin.php b/app/code/Magento/Backend/App/Action/Plugin/LoadDesignPlugin.php new file mode 100644 index 0000000000000..7075e1b05e7db --- /dev/null +++ b/app/code/Magento/Backend/App/Action/Plugin/LoadDesignPlugin.php @@ -0,0 +1,46 @@ +designLoader = $designLoader; + } + + /** + * Initiates design before dispatching Backend Actions. + * + * @param AbstractAction $backendAction + * @param RequestInterface $request + * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeDispatch(AbstractAction $backendAction, RequestInterface $request) + { + $this->designLoader->load(); + } +} diff --git a/app/code/Magento/Backend/etc/adminhtml/di.xml b/app/code/Magento/Backend/etc/adminhtml/di.xml index 5f566396ab500..1bfc504cf50e9 100644 --- a/app/code/Magento/Backend/etc/adminhtml/di.xml +++ b/app/code/Magento/Backend/etc/adminhtml/di.xml @@ -60,8 +60,9 @@ - - + + + diff --git a/app/code/Magento/Captcha/Observer/CheckUserForgotPasswordBackendObserver.php b/app/code/Magento/Captcha/Observer/CheckUserForgotPasswordBackendObserver.php index e11e48a527169..21d7e2f1993b7 100644 --- a/app/code/Magento/Captcha/Observer/CheckUserForgotPasswordBackendObserver.php +++ b/app/code/Magento/Captcha/Observer/CheckUserForgotPasswordBackendObserver.php @@ -3,19 +3,28 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Captcha\Observer; +use Magento\Captcha\Helper\Data as CaptchaHelper; +use Magento\Framework\App\Action\Action; +use Magento\Framework\App\ActionFlag; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Event\Observer as Event; use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\Session\SessionManagerInterface; /** - * Class CheckUserForgotPasswordBackendObserver + * Handle request for Forgot Password * * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class CheckUserForgotPasswordBackendObserver implements ObserverInterface { /** - * @var \Magento\Captcha\Helper\Data + * @var CaptchaHelper */ protected $_helper; @@ -25,62 +34,70 @@ class CheckUserForgotPasswordBackendObserver implements ObserverInterface protected $captchaStringResolver; /** - * @var \Magento\Framework\Session\SessionManagerInterface + * @var SessionManagerInterface */ protected $_session; /** - * @var \Magento\Framework\App\ActionFlag + * @var ActionFlag */ protected $_actionFlag; /** - * @var \Magento\Framework\Message\ManagerInterface + * @var ManagerInterface */ protected $messageManager; /** - * @param \Magento\Captcha\Helper\Data $helper + * @var RequestInterface + */ + private $request; + + /** + * @param CaptchaHelper $helper * @param CaptchaStringResolver $captchaStringResolver - * @param \Magento\Framework\Session\SessionManagerInterface $session - * @param \Magento\Framework\App\ActionFlag $actionFlag - * @param \Magento\Framework\Message\ManagerInterface $messageManager + * @param SessionManagerInterface $session + * @param ActionFlag $actionFlag + * @param ManagerInterface $messageManager + * @param RequestInterface|null $request */ public function __construct( - \Magento\Captcha\Helper\Data $helper, + CaptchaHelper $helper, CaptchaStringResolver $captchaStringResolver, - \Magento\Framework\Session\SessionManagerInterface $session, - \Magento\Framework\App\ActionFlag $actionFlag, - \Magento\Framework\Message\ManagerInterface $messageManager + SessionManagerInterface $session, + ActionFlag $actionFlag, + ManagerInterface $messageManager, + RequestInterface $request = null ) { $this->_helper = $helper; $this->captchaStringResolver = $captchaStringResolver; $this->_session = $session; $this->_actionFlag = $actionFlag; $this->messageManager = $messageManager; + $this->request = $request ?? ObjectManager::getInstance()->get(RequestInterface::class); } /** * Check Captcha On User Login Backend Page * - * @param \Magento\Framework\Event\Observer $observer - * @throws \Magento\Framework\Exception\Plugin\AuthenticationException + * @param Event $observer * @return $this + * @throws \Magento\Framework\Exception\Plugin\AuthenticationException */ - public function execute(\Magento\Framework\Event\Observer $observer) + public function execute(Event $observer) { $formId = 'backend_forgotpassword'; $captchaModel = $this->_helper->getCaptcha($formId); $controller = $observer->getControllerAction(); - $email = (string)$observer->getControllerAction()->getRequest()->getParam('email'); - $params = $observer->getControllerAction()->getRequest()->getParams(); - if (!empty($email) - && !empty($params) + $params = $this->request->getParams(); + $email = (string)$this->request->getParam('email'); + if (!empty($params) + && !empty($email) && $captchaModel->isRequired() - && !$captchaModel->isCorrect($this->captchaStringResolver->resolve($controller->getRequest(), $formId)) + && !$captchaModel->isCorrect($this->captchaStringResolver->resolve($this->request, $formId)) ) { - $this->_session->setEmail((string)$controller->getRequest()->getPost('email')); - $this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true); + $this->_session->setEmail($email); + $this->_actionFlag->set('', Action::FLAG_NO_DISPATCH, true); $this->messageManager->addErrorMessage(__('Incorrect CAPTCHA')); $controller->getResponse()->setRedirect( $controller->getUrl('*/*/forgotpassword', ['_nosecret' => true]) diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php index 584e7eb2e215f..9d3aa88ed9be4 100644 --- a/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php @@ -101,6 +101,7 @@ protected function setUp() ->getMockForAbstractClass(); $this->actionFlagMock = $this->createMock(ActionFlag::class); $this->messageManagerMock = $this->createMock(ManagerInterface::class); + $this->requestMock = $this->createMock(HttpRequest::class); $objectManager = new ObjectManagerHelper($this); $this->observer = $objectManager->getObject( @@ -110,7 +111,8 @@ protected function setUp() 'captchaStringResolver' => $this->captchaStringResolverMock, '_session' => $this->sessionMock, '_actionFlag' => $this->actionFlagMock, - 'messageManager' => $this->messageManagerMock + 'messageManager' => $this->messageManagerMock, + 'request' => $this->requestMock ] ); @@ -122,16 +124,12 @@ protected function setUp() ->with($formId) ->willReturn($this->captchaMock); - $this->requestMock = $this->createMock(HttpRequest::class); $this->httpResponseMock = $this->createMock(HttpResponse::class); $this->controllerMock = $this->getMockBuilder(Action::class) ->disableOriginalConstructor() - ->setMethods(['getUrl', 'getRequest', 'getResponse']) + ->setMethods(['getUrl', 'getResponse']) ->getMockForAbstractClass(); - $this->controllerMock->expects($this->any()) - ->method('getRequest') - ->willReturn($this->requestMock); $this->controllerMock->expects($this->any()) ->method('getResponse') ->willReturn($this->httpResponseMock); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassDelete.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassDelete.php index 7fa9d36163502..c779c01cd7d71 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassDelete.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/MassDelete.php @@ -8,15 +8,13 @@ namespace Magento\Catalog\Controller\Adminhtml\Product; -use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; -use Magento\Framework\Controller\ResultFactory; use Magento\Backend\App\Action\Context; -use Magento\Ui\Component\MassAction\Filter; -use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\Exception\CouldNotSaveException; -use Magento\Framework\Exception\StateException; +use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; +use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; +use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\LocalizedException; +use Magento\Ui\Component\MassAction\Filter; use Psr\Log\LoggerInterface; /** diff --git a/app/code/Magento/Customer/Model/App/Action/ContextPlugin.php b/app/code/Magento/Customer/Model/App/Action/ContextPlugin.php index b8c83551ee381..5d926b47ca446 100644 --- a/app/code/Magento/Customer/Model/App/Action/ContextPlugin.php +++ b/app/code/Magento/Customer/Model/App/Action/ContextPlugin.php @@ -8,13 +8,12 @@ use Magento\Customer\Model\Context; use Magento\Customer\Model\GroupManagement; -use Magento\Framework\App\Action\AbstractAction; -use Magento\Framework\App\RequestInterface; use Magento\Customer\Model\Session; +use Magento\Framework\App\ActionInterface; use Magento\Framework\App\Http\Context as HttpContext; /** - * Class ContextPlugin + * Introduces Context information for ActionInterface of Customer Action */ class ContextPlugin { @@ -41,12 +40,11 @@ public function __construct(Session $customerSession, HttpContext $httpContext) /** * Set customer group and customer session id to HTTP context * - * @param AbstractAction $subject - * @param RequestInterface $request + * @param ActionInterface $subject * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function beforeDispatch(AbstractAction $subject, RequestInterface $request) + public function beforeExecute(ActionInterface $subject) { $this->httpContext->setValue( Context::CONTEXT_GROUP, diff --git a/app/code/Magento/Customer/Model/Plugin/CustomerNotification.php b/app/code/Magento/Customer/Model/Plugin/CustomerNotification.php index 577c97a19268a..db694ad3295ce 100644 --- a/app/code/Magento/Customer/Model/Plugin/CustomerNotification.php +++ b/app/code/Magento/Customer/Model/Plugin/CustomerNotification.php @@ -3,22 +3,23 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Model\Plugin; use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Model\Customer\NotificationStorage; use Magento\Customer\Model\Session; -use Magento\Framework\App\Action\AbstractAction; +use Magento\Framework\App\ActionInterface; use Magento\Framework\App\Area; +use Magento\Framework\App\HttpRequestInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\State; use Magento\Framework\Exception\NoSuchEntityException; use Psr\Log\LoggerInterface; /** - * Plugin before \Magento\Framework\App\Action\AbstractAction::dispatch. - * - * Plugin to remove notifications from cache. + * Refresh the Customer session if `UpdateSession` notification registered */ class CustomerNotification { @@ -47,6 +48,11 @@ class CustomerNotification */ private $logger; + /** + * @var RequestInterface|\Magento\Framework\App\Request\Http + */ + private $request; + /** * Initialize dependencies. * @@ -55,39 +61,37 @@ class CustomerNotification * @param State $state * @param CustomerRepositoryInterface $customerRepository * @param LoggerInterface $logger + * @param RequestInterface|null $request */ public function __construct( Session $session, NotificationStorage $notificationStorage, State $state, CustomerRepositoryInterface $customerRepository, - LoggerInterface $logger + LoggerInterface $logger, + RequestInterface $request ) { $this->session = $session; $this->notificationStorage = $notificationStorage; $this->state = $state; $this->customerRepository = $customerRepository; $this->logger = $logger; + $this->request = $request; } /** - * Removes notifications from cache. + * Refresh the customer session on frontend post requests if an update session notification is registered. * - * @param AbstractAction $subject - * @param RequestInterface $request + * @param ActionInterface $subject * @return void + * @throws \Magento\Framework\Exception\LocalizedException * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function beforeDispatch(AbstractAction $subject, RequestInterface $request) + public function beforeExecute(ActionInterface $subject) { $customerId = $this->session->getCustomerId(); - if ($this->state->getAreaCode() == Area::AREA_FRONTEND && $request->isPost() - && $this->notificationStorage->isExists( - NotificationStorage::UPDATE_CUSTOMER_SESSION, - $customerId - ) - ) { + if ($this->isFrontendRequest() && $this->isPostRequest() && $this->isSessionUpdateRegisteredFor($customerId)) { try { $this->session->regenerateId(); $customer = $this->customerRepository->getById($customerId); @@ -99,4 +103,36 @@ public function beforeDispatch(AbstractAction $subject, RequestInterface $reques } } } + + /** + * Because RequestInterface has no isPost method the check is requied before calling it. + * + * @return bool + */ + private function isPostRequest(): bool + { + return $this->request instanceof HttpRequestInterface && $this->request->isPost(); + } + + /** + * Check if the current application area is frontend. + * + * @return bool + * @throws \Magento\Framework\Exception\LocalizedException + */ + private function isFrontendRequest(): bool + { + return $this->state->getAreaCode() === Area::AREA_FRONTEND; + } + + /** + * True if the session for the given customer ID needs to be refreshed. + * + * @param int $customerId + * @return bool + */ + private function isSessionUpdateRegisteredFor($customerId): bool + { + return $this->notificationStorage->isExists(NotificationStorage::UPDATE_CUSTOMER_SESSION, $customerId); + } } diff --git a/app/code/Magento/Customer/Model/Visitor.php b/app/code/Magento/Customer/Model/Visitor.php index 5fa1af69e9bdd..53745aa7a30c6 100644 --- a/app/code/Magento/Customer/Model/Visitor.php +++ b/app/code/Magento/Customer/Model/Visitor.php @@ -6,8 +6,23 @@ namespace Magento\Customer\Model; +use Magento\Customer\Api\Data\CustomerInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\Request; use Magento\Framework\App\RequestSafetyInterface; +use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\Event\Observer as EventObserver; +use Magento\Framework\HTTP\Header; +use Magento\Framework\Indexer\IndexerRegistry; +use Magento\Framework\Model\AbstractModel; +use Magento\Framework\Model\Context as ModelContext; +use Magento\Framework\Model\ResourceModel\AbstractResource; +use Magento\Framework\Registry; +use Magento\Framework\Session\Config as SessionConfig; +use Magento\Framework\Session\SessionManagerInterface; +use Magento\Framework\Stdlib\DateTime; +use Magento\Store\Model\ScopeInterface; /** * Class Visitor @@ -17,15 +32,13 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ -class Visitor extends \Magento\Framework\Model\AbstractModel +class Visitor extends AbstractModel { const VISITOR_TYPE_CUSTOMER = 'c'; - const VISITOR_TYPE_VISITOR = 'v'; - const DEFAULT_ONLINE_MINUTES_INTERVAL = 15; - const XML_PATH_ONLINE_INTERVAL = 'customer/online_customers/online_minutes_interval'; + private const SECONDS_24_HOURS = 86400; /** * @var string[] @@ -33,12 +46,12 @@ class Visitor extends \Magento\Framework\Model\AbstractModel protected $ignoredUserAgents; /** - * @var \Magento\Framework\Session\SessionManagerInterface + * @var SessionManagerInterface */ protected $session; /** - * @var \Magento\Framework\HTTP\Header + * @var Header */ protected $httpHeader; @@ -57,17 +70,17 @@ class Visitor extends \Magento\Framework\Model\AbstractModel /** * Core store config * - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface */ protected $scopeConfig; /** - * @var \Magento\Framework\Stdlib\DateTime + * @var DateTime */ protected $dateTime; /** - * @var \Magento\Framework\Indexer\IndexerRegistry + * @var IndexerRegistry */ protected $indexerRegistry; @@ -77,15 +90,15 @@ class Visitor extends \Magento\Framework\Model\AbstractModel private $requestSafety; /** - * @param \Magento\Framework\Model\Context $context - * @param \Magento\Framework\Registry $registry - * @param \Magento\Framework\Session\SessionManagerInterface $session - * @param \Magento\Framework\HTTP\Header $httpHeader - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Framework\Stdlib\DateTime $dateTime - * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry - * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource - * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection + * @param ModelContext $context + * @param Registry $registry + * @param SessionManagerInterface $session + * @param Header $httpHeader + * @param ScopeConfigInterface $scopeConfig + * @param DateTime $dateTime + * @param IndexerRegistry $indexerRegistry + * @param AbstractResource|null $resource + * @param AbstractDb|null $resourceCollection * @param array $ignoredUserAgents * @param array $ignores * @param array $data @@ -94,15 +107,15 @@ class Visitor extends \Magento\Framework\Model\AbstractModel * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - \Magento\Framework\Model\Context $context, - \Magento\Framework\Registry $registry, - \Magento\Framework\Session\SessionManagerInterface $session, - \Magento\Framework\HTTP\Header $httpHeader, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Framework\Stdlib\DateTime $dateTime, - \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry, - \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, + ModelContext $context, + Registry $registry, + SessionManagerInterface $session, + Header $httpHeader, + ScopeConfigInterface $scopeConfig, + DateTime $dateTime, + IndexerRegistry $indexerRegistry, + AbstractResource $resource = null, + AbstractDb $resourceCollection = null, array $ignoredUserAgents = [], array $ignores = [], array $data = [], @@ -126,7 +139,7 @@ public function __construct( */ protected function _construct() { - $this->_init(\Magento\Customer\Model\ResourceModel\Visitor::class); + $this->_init(ResourceModel\Visitor::class); $userAgent = $this->httpHeader->getHttpUserAgent(); if ($this->ignoredUserAgents) { if (in_array($userAgent, $this->ignoredUserAgents)) { @@ -139,7 +152,7 @@ protected function _construct() * Skip request logging * * @param bool $skipRequestLogging - * @return \Magento\Customer\Model\Visitor + * @return Visitor */ public function setSkipRequestLogging($skipRequestLogging) { @@ -148,12 +161,10 @@ public function setSkipRequestLogging($skipRequestLogging) } /** - * Initialization visitor by request + * Initialization visitor by request. Used in event "controller_action_predispatch" * - * Used in event "controller_action_predispatch" - * - * @param \Magento\Framework\Event\Observer $observer - * @return \Magento\Customer\Model\Visitor + * @param EventObserver $observer + * @return Visitor */ public function initByRequest($observer) { @@ -168,7 +179,7 @@ public function initByRequest($observer) } } - $this->setLastVisitAt((new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)); + $this->setLastVisitAt((new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT)); // prevent saving Visitor for safe methods, e.g. GET request if ($this->requestSafety->isSafeMethod()) { @@ -189,8 +200,8 @@ public function initByRequest($observer) * * Used in event "controller_action_postdispatch" * - * @param \Magento\Framework\Event\Observer $observer - * @return \Magento\Customer\Model\Visitor + * @param EventObserver $observer + * @return Visitor */ public function saveByRequest($observer) { @@ -215,13 +226,13 @@ public function saveByRequest($observer) /** * Returns true if the module is required * - * @param \Magento\Framework\Event\Observer $observer + * @param EventObserver $observer * @return bool */ public function isModuleIgnored($observer) { if (is_array($this->ignores) && $observer) { - $curModule = $observer->getEvent()->getControllerAction()->getRequest()->getRouteName(); + $curModule = $this->requestSafety->getRouteName(); if (isset($this->ignores[$curModule])) { return true; } @@ -234,12 +245,12 @@ public function isModuleIgnored($observer) * * Used in event "customer_login" * - * @param \Magento\Framework\Event\Observer $observer - * @return \Magento\Customer\Model\Visitor + * @param EventObserver $observer + * @return Visitor */ public function bindCustomerLogin($observer) { - /** @var \Magento\Customer\Api\Data\CustomerInterface $customer */ + /** @var CustomerInterface $customer */ $customer = $observer->getEvent()->getCustomer(); if (!$this->getCustomerId()) { $this->setDoCustomerLogin(true); @@ -253,8 +264,8 @@ public function bindCustomerLogin($observer) * * Used in event "customer_logout" * - * @param \Magento\Framework\Event\Observer $observer - * @return \Magento\Customer\Model\Visitor + * @param EventObserver $observer + * @return Visitor * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function bindCustomerLogout($observer) @@ -268,8 +279,8 @@ public function bindCustomerLogout($observer) /** * Create binding of checkout quote * - * @param \Magento\Framework\Event\Observer $observer - * @return \Magento\Customer\Model\Visitor + * @param EventObserver $observer + * @return Visitor */ public function bindQuoteCreate($observer) { @@ -286,8 +297,8 @@ public function bindQuoteCreate($observer) /** * Destroy binding of checkout quote * - * @param \Magento\Framework\Event\Observer $observer - * @return \Magento\Customer\Model\Visitor + * @param EventObserver $observer + * @return Visitor */ public function bindQuoteDestroy($observer) { @@ -305,10 +316,10 @@ public function bindQuoteDestroy($observer) */ public function getCleanTime() { - return $this->scopeConfig->getValue( - \Magento\Framework\Session\Config::XML_PATH_COOKIE_LIFETIME, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ) + 86400; + return self::SECONDS_24_HOURS + $this->scopeConfig->getValue( + SessionConfig::XML_PATH_COOKIE_LIFETIME, + ScopeInterface::SCOPE_STORE + ); } /** @@ -331,7 +342,7 @@ public function getOnlineInterval() { $configValue = (int)$this->scopeConfig->getValue( static::XML_PATH_ONLINE_INTERVAL, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ScopeInterface::SCOPE_STORE ); return $configValue ?: static::DEFAULT_ONLINE_MINUTES_INTERVAL; } diff --git a/app/code/Magento/Customer/Test/Unit/Model/App/Action/ContextPluginTest.php b/app/code/Magento/Customer/Test/Unit/Model/App/Action/ContextPluginTest.php index 4b89fda7c7051..4e722a36b57da 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/App/Action/ContextPluginTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/App/Action/ContextPluginTest.php @@ -6,57 +6,56 @@ namespace Magento\Customer\Test\Unit\Model\App\Action; +use Magento\Customer\Model\App\Action\ContextPlugin; use Magento\Customer\Model\Context; +use Magento\Customer\Model\Session; +use Magento\Framework\App\Action\Action; +use Magento\Framework\App\Http\Context as HttpContext; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; /** - * Class ContextPluginTest + * Unit Tests to cover ContextPlugin for Action Context */ -class ContextPluginTest extends \PHPUnit\Framework\TestCase +class ContextPluginTest extends TestCase { + const STUB_CUSTOMER_GROUP = 'UAH'; + const STUB_CUSTOMER_NOT_LOGGED_IN = 0; /** - * @var \Magento\Customer\Model\App\Action\ContextPlugin + * @var ContextPlugin */ protected $plugin; /** - * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var Session|MockObject */ protected $customerSessionMock; /** - * @var \Magento\Framework\App\Http\Context $httpContext|\PHPUnit_Framework_MockObject_MockObject + * @var HttpContext|MockObject */ protected $httpContextMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Action|MockObject */ protected $subjectMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - /** * Set up */ protected function setUp() { - $this->customerSessionMock = $this->createMock(\Magento\Customer\Model\Session::class); - $this->httpContextMock = $this->createMock(\Magento\Framework\App\Http\Context::class); - $this->subjectMock = $this->createMock(\Magento\Framework\App\Action\Action::class); - $this->requestMock = $this->createMock(\Magento\Framework\App\RequestInterface::class); - $this->plugin = new \Magento\Customer\Model\App\Action\ContextPlugin( + $this->customerSessionMock = $this->createMock(Session::class); + $this->httpContextMock = $this->createMock(HttpContext::class); + $this->subjectMock = $this->createMock(Action::class); + $this->plugin = new ContextPlugin( $this->customerSessionMock, $this->httpContextMock ); } - /** - * Test aroundDispatch - */ - public function testBeforeDispatch() + public function testBeforeExecute() { $this->customerSessionMock->expects($this->once()) ->method('getCustomerGroupId') @@ -69,11 +68,11 @@ public function testBeforeDispatch() ->will( $this->returnValueMap( [ - [Context::CONTEXT_GROUP, 'UAH', $this->httpContextMock], - [Context::CONTEXT_AUTH, 0, $this->httpContextMock], + [Context::CONTEXT_GROUP, self::STUB_CUSTOMER_GROUP, $this->httpContextMock], + [Context::CONTEXT_AUTH, self::STUB_CUSTOMER_NOT_LOGGED_IN, $this->httpContextMock], ] ) ); - $this->plugin->beforeDispatch($this->subjectMock, $this->requestMock); + $this->plugin->beforeExecute($this->subjectMock); } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerNotificationTest.php b/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerNotificationTest.php index c3c853bca1469..74a5a002c7845 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerNotificationTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerNotificationTest.php @@ -3,79 +3,87 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Customer\Test\Unit\Model\Plugin; -use Magento\Backend\App\AbstractAction; use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Api\Data\CustomerInterface; use Magento\Customer\Model\Customer\NotificationStorage; use Magento\Customer\Model\Plugin\CustomerNotification; use Magento\Customer\Model\Session; +use Magento\Framework\App\ActionInterface; use Magento\Framework\App\Area; +use Magento\Framework\App\HttpRequestInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\State; use Magento\Framework\Exception\NoSuchEntityException; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; class CustomerNotificationTest extends \PHPUnit\Framework\TestCase { - /** @var Session|\PHPUnit_Framework_MockObject_MockObject */ + private const STUB_CUSTOMER_ID = 1; + + /** + * @var Session|MockObject + */ private $sessionMock; - /** @var NotificationStorage|\PHPUnit_Framework_MockObject_MockObject */ + /** + * @var NotificationStorage|MockObject + */ private $notificationStorageMock; - /** @var CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** + * @var CustomerRepositoryInterface|MockObject + */ private $customerRepositoryMock; - /** @var State|\PHPUnit_Framework_MockObject_MockObject */ + /** + * @var State|MockObject + */ private $appStateMock; - /** @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** + * @var RequestInterface|MockObject + */ private $requestMock; - /** @var AbstractAction|\PHPUnit_Framework_MockObject_MockObject */ - private $abstractActionMock; + /** + * @var ActionInterface|MockObject + */ + private $actionMock; - /** @var LoggerInterface */ + /** + * @var LoggerInterface|MockObject + */ private $loggerMock; - /** @var CustomerNotification */ + /** + * @var CustomerNotification + */ private $plugin; - /** @var int */ - private static $customerId = 1; - protected function setUp() { - $this->sessionMock = $this->getMockBuilder(Session::class) - ->disableOriginalConstructor() - ->setMethods(['getCustomerId', 'setCustomerData', 'setCustomerGroupId', 'regenerateId']) - ->getMock(); - $this->notificationStorageMock = $this->getMockBuilder(NotificationStorage::class) - ->disableOriginalConstructor() - ->setMethods(['isExists', 'remove']) - ->getMock(); - $this->customerRepositoryMock = $this->getMockBuilder(CustomerRepositoryInterface::class) - ->getMockForAbstractClass(); - $this->abstractActionMock = $this->getMockBuilder(AbstractAction::class) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $this->requestMock = $this->getMockBuilder(RequestInterface::class) - ->setMethods(['isPost']) - ->getMockForAbstractClass(); - $this->appStateMock = $this->getMockBuilder(State::class) - ->disableOriginalConstructor() - ->setMethods(['getAreaCode']) + $this->sessionMock = $this->createMock(Session::class); + $this->sessionMock->method('getCustomerId')->willReturn(self::STUB_CUSTOMER_ID); + + $this->customerRepositoryMock = $this->createMock(CustomerRepositoryInterface::class); + $this->actionMock = $this->createMock(ActionInterface::class); + $this->requestMock = $this->getMockBuilder([RequestInterface::class, HttpRequestInterface::class]) ->getMock(); + $this->requestMock->method('isPost')->willReturn(true); + + $this->loggerMock = $this->createMock(LoggerInterface::class); - $this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class); + $this->appStateMock = $this->createMock(State::class); $this->appStateMock->method('getAreaCode')->willReturn(Area::AREA_FRONTEND); - $this->requestMock->method('isPost')->willReturn(true); - $this->sessionMock->method('getCustomerId')->willReturn(self::$customerId); + + $this->notificationStorageMock = $this->createMock(NotificationStorage::class); $this->notificationStorageMock->expects($this->any()) ->method('isExists') - ->with(NotificationStorage::UPDATE_CUSTOMER_SESSION, self::$customerId) + ->with(NotificationStorage::UPDATE_CUSTOMER_SESSION, self::STUB_CUSTOMER_ID) ->willReturn(true); $this->plugin = new CustomerNotification( @@ -83,41 +91,42 @@ protected function setUp() $this->notificationStorageMock, $this->appStateMock, $this->customerRepositoryMock, - $this->loggerMock + $this->loggerMock, + $this->requestMock ); } - public function testBeforeDispatch() + public function testBeforeExecute() { - $customerGroupId =1; + $customerGroupId = 1; - $customerMock = $this->getMockForAbstractClass(CustomerInterface::class); + $customerMock = $this->createMock(CustomerInterface::class); $customerMock->method('getGroupId')->willReturn($customerGroupId); - $customerMock->method('getId')->willReturn(self::$customerId); + $customerMock->method('getId')->willReturn(self::STUB_CUSTOMER_ID); $this->customerRepositoryMock->expects($this->once()) ->method('getById') - ->with(self::$customerId) + ->with(self::STUB_CUSTOMER_ID) ->willReturn($customerMock); $this->notificationStorageMock->expects($this->once()) ->method('remove') - ->with(NotificationStorage::UPDATE_CUSTOMER_SESSION, self::$customerId); + ->with(NotificationStorage::UPDATE_CUSTOMER_SESSION, self::STUB_CUSTOMER_ID); $this->sessionMock->expects($this->once())->method('setCustomerData')->with($customerMock); $this->sessionMock->expects($this->once())->method('setCustomerGroupId')->with($customerGroupId); $this->sessionMock->expects($this->once())->method('regenerateId'); - $this->plugin->beforeDispatch($this->abstractActionMock, $this->requestMock); + $this->plugin->beforeExecute($this->actionMock); } public function testBeforeDispatchWithNoCustomerFound() { $this->customerRepositoryMock->method('getById') - ->with(self::$customerId) + ->with(self::STUB_CUSTOMER_ID) ->willThrowException(new NoSuchEntityException()); $this->loggerMock->expects($this->once()) ->method('error'); - $this->plugin->beforeDispatch($this->abstractActionMock, $this->requestMock); + $this->plugin->beforeExecute($this->actionMock); } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/VisitorTest.php b/app/code/Magento/Customer/Test/Unit/Model/VisitorTest.php index ec787b9d3c873..c9cd525d71c49 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/VisitorTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/VisitorTest.php @@ -6,16 +6,24 @@ namespace Magento\Customer\Test\Unit\Model; +use Magento\Customer\Model\ResourceModel\Visitor as VisitorResourceModel; +use Magento\Customer\Model\Session; +use Magento\Customer\Model\Visitor as VisitorModel; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\DataObject; +use Magento\Framework\Registry; +use Magento\Framework\Session\SessionManagerInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; /** - * Class VisitorTest - * @package Magento\Customer\Model + * Unit Tests to cover Visitor Model */ -class VisitorTest extends \PHPUnit\Framework\TestCase +class VisitorTest extends TestCase { /** - * @var \Magento\Customer\Model\Visitor + * @var VisitorModel */ protected $visitor; @@ -25,31 +33,37 @@ class VisitorTest extends \PHPUnit\Framework\TestCase protected $objectManagerHelper; /** - * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + * @var Registry|MockObject */ - protected $registry; + protected $registryMock; /** - * @var \Magento\Customer\Model\ResourceModel\Visitor|\PHPUnit_Framework_MockObject_MockObject + * @var VisitorResourceModel|MockObject */ - protected $resource; + protected $visitorResourceModelMock; /** - * @var \Magento\Framework\Session\SessionManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var SessionManagerInterface|MockObject */ - protected $session; + protected $sessionMock; + + /** + * @var HttpRequest|MockObject + */ + private $httpRequestMock; protected function setUp() { - $this->registry = $this->createMock(\Magento\Framework\Registry::class); - $this->session = $this->getMockBuilder(\Magento\Customer\Model\Session::class) + $this->registryMock = $this->createMock(Registry::class); + $this->sessionMock = $this->getMockBuilder(Session::class) ->disableOriginalConstructor() ->setMethods(['getSessionId', 'getVisitorData', 'setVisitorData']) ->getMock(); + $this->httpRequestMock = $this->createMock(HttpRequest::class); $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->resource = $this->getMockBuilder(\Magento\Customer\Model\ResourceModel\Visitor::class) + $this->visitorResourceModelMock = $this->getMockBuilder(VisitorResourceModel::class) ->setMethods([ 'beginTransaction', '__sleep', @@ -60,27 +74,28 @@ protected function setUp() 'commit', 'clean', ])->disableOriginalConstructor()->getMock(); - $this->resource->expects($this->any())->method('getIdFieldName')->willReturn('visitor_id'); - $this->resource->expects($this->any())->method('addCommitCallback')->willReturnSelf(); + $this->visitorResourceModelMock->expects($this->any())->method('getIdFieldName')->willReturn('visitor_id'); + $this->visitorResourceModelMock->expects($this->any())->method('addCommitCallback')->willReturnSelf(); $arguments = $this->objectManagerHelper->getConstructArguments( - \Magento\Customer\Model\Visitor::class, + VisitorModel::class, [ - 'registry' => $this->registry, - 'session' => $this->session, - 'resource' => $this->resource, + 'registry' => $this->registryMock, + 'session' => $this->sessionMock, + 'resource' => $this->visitorResourceModelMock, + 'request' => $this->httpRequestMock, ] ); - $this->visitor = $this->objectManagerHelper->getObject(\Magento\Customer\Model\Visitor::class, $arguments); + $this->visitor = $this->objectManagerHelper->getObject(VisitorModel::class, $arguments); } public function testInitByRequest() { $oldSessionId = 'asdfhasdfjhkj2198sadf8sdf897'; $newSessionId = 'bsdfhasdfjhkj2198sadf8sdf897'; - $this->session->expects($this->any())->method('getSessionId')->willReturn($newSessionId); - $this->session->expects($this->atLeastOnce())->method('getVisitorData') + $this->sessionMock->expects($this->any())->method('getSessionId')->willReturn($newSessionId); + $this->sessionMock->expects($this->atLeastOnce())->method('getVisitorData') ->willReturn(['session_id' => $oldSessionId]); $this->visitor->initByRequest(null); $this->assertEquals($newSessionId, $this->visitor->getSessionId()); @@ -88,33 +103,32 @@ public function testInitByRequest() public function testSaveByRequest() { - $this->session->expects($this->once())->method('setVisitorData')->will($this->returnSelf()); + $this->sessionMock->expects($this->once())->method('setVisitorData')->will($this->returnSelf()); $this->assertSame($this->visitor, $this->visitor->saveByRequest(null)); } public function testIsModuleIgnored() { $this->visitor = $this->objectManagerHelper->getObject( - \Magento\Customer\Model\Visitor::class, + VisitorModel::class, [ - 'registry' => $this->registry, - 'session' => $this->session, - 'resource' => $this->resource, + 'registry' => $this->registryMock, + 'session' => $this->sessionMock, + 'resource' => $this->visitorResourceModelMock, 'ignores' => ['test_route_name' => true], + 'requestSafety' => $this->httpRequestMock, ] ); - $request = new \Magento\Framework\DataObject(['route_name' => 'test_route_name']); - $action = new \Magento\Framework\DataObject(['request' => $request]); - $event = new \Magento\Framework\DataObject(['controller_action' => $action]); - $observer = new \Magento\Framework\DataObject(['event' => $event]); + $this->httpRequestMock->method('getRouteName')->willReturn('test_route_name'); + $observer = new DataObject(); $this->assertTrue($this->visitor->isModuleIgnored($observer)); } public function testBindCustomerLogin() { - $customer = new \Magento\Framework\DataObject(['id' => '1']); - $observer = new \Magento\Framework\DataObject([ - 'event' => new \Magento\Framework\DataObject(['customer' => $customer]), + $customer = new DataObject(['id' => '1']); + $observer = new DataObject([ + 'event' => new DataObject(['customer' => $customer]), ]); $this->visitor->bindCustomerLogin($observer); @@ -130,7 +144,7 @@ public function testBindCustomerLogin() public function testBindCustomerLogout() { - $observer = new \Magento\Framework\DataObject(); + $observer = new DataObject(); $this->visitor->setCustomerId('1'); $this->visitor->bindCustomerLogout($observer); @@ -143,9 +157,9 @@ public function testBindCustomerLogout() public function testBindQuoteCreate() { - $quote = new \Magento\Framework\DataObject(['id' => '1', 'is_checkout_cart' => true]); - $observer = new \Magento\Framework\DataObject([ - 'event' => new \Magento\Framework\DataObject(['quote' => $quote]), + $quote = new DataObject(['id' => '1', 'is_checkout_cart' => true]); + $observer = new DataObject([ + 'event' => new DataObject(['quote' => $quote]), ]); $this->visitor->bindQuoteCreate($observer); $this->assertTrue($this->visitor->getDoQuoteCreate()); @@ -153,9 +167,9 @@ public function testBindQuoteCreate() public function testBindQuoteDestroy() { - $quote = new \Magento\Framework\DataObject(['id' => '1']); - $observer = new \Magento\Framework\DataObject([ - 'event' => new \Magento\Framework\DataObject(['quote' => $quote]), + $quote = new DataObject(['id' => '1']); + $observer = new DataObject([ + 'event' => new DataObject(['quote' => $quote]), ]); $this->visitor->bindQuoteDestroy($observer); $this->assertTrue($this->visitor->getDoQuoteDestroy()); @@ -163,7 +177,10 @@ public function testBindQuoteDestroy() public function testClean() { - $this->resource->expects($this->once())->method('clean')->with($this->visitor)->willReturnSelf(); + $this->visitorResourceModelMock->expects($this->once()) + ->method('clean') + ->with($this->visitor) + ->willReturnSelf(); $this->visitor->clean(); } } diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml index be219a81fd990..60a2da9d6dfa7 100644 --- a/app/code/Magento/Customer/etc/di.xml +++ b/app/code/Magento/Customer/etc/di.xml @@ -354,7 +354,7 @@ - + diff --git a/app/code/Magento/Customer/etc/frontend/di.xml b/app/code/Magento/Customer/etc/frontend/di.xml index 3b9675178c052..a479d0d2af328 100644 --- a/app/code/Magento/Customer/etc/frontend/di.xml +++ b/app/code/Magento/Customer/etc/frontend/di.xml @@ -20,8 +20,8 @@ - - + _storeManager = $storeManager; } /** - * @param \Magento\Framework\App\Action\AbstractAction $subject - * @param \Magento\Framework\App\RequestInterface $request + * Verify before execute + * + * @param ActionInterface $subject * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @throws \Magento\Framework\Exception\State\InitException */ - public function beforeDispatch( - \Magento\Framework\App\Action\AbstractAction $subject, - \Magento\Framework\App\RequestInterface $request - ) { + public function beforeExecute(ActionInterface $subject) + { if (!$this->_storeManager->getStore()->isActive()) { - throw new \Magento\Framework\Exception\State\InitException( + throw new InitException( __('Current store is not active.') ); } diff --git a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/StoreCheckTest.php b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/StoreCheckTest.php index 93bd4f2ccfba4..9ecd640b246af 100644 --- a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/StoreCheckTest.php +++ b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/StoreCheckTest.php @@ -5,37 +5,38 @@ */ namespace Magento\Store\Test\Unit\App\Action\Plugin; +use Magento\Framework\App\Action\AbstractAction; +use Magento\Store\App\Action\Plugin\StoreCheck; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use PHPUnit\Framework\MockObject\MockObject; + class StoreCheckTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Store\App\Action\Plugin\StoreCheck + * @var StoreCheck */ protected $_plugin; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var StoreManagerInterface|MockObject */ protected $_storeManagerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Store|MockObject */ protected $_storeMock; /** - * @var \Magento\Framework\App\Action\AbstractAction|\PHPUnit_Framework_MockObject_MockObject + * @var AbstractAction|MockObject */ protected $subjectMock; - /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - protected function setUp() { - $this->_storeManagerMock = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class); - $this->_storeMock = $this->createMock(\Magento\Store\Model\Store::class); + $this->_storeManagerMock = $this->createMock(StoreManagerInterface::class); + $this->_storeMock = $this->createMock(Store::class); $this->_storeManagerMock->expects( $this->any() )->method( @@ -43,28 +44,27 @@ protected function setUp() )->will( $this->returnValue($this->_storeMock) ); - $this->requestMock = $this->createMock(\Magento\Framework\App\RequestInterface::class); - $this->subjectMock = $this->getMockBuilder(\Magento\Framework\App\Action\AbstractAction::class) + $this->subjectMock = $this->getMockBuilder(AbstractAction::class) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $this->_plugin = new \Magento\Store\App\Action\Plugin\StoreCheck($this->_storeManagerMock); + $this->_plugin = new StoreCheck($this->_storeManagerMock); } /** * @expectedException \Magento\Framework\Exception\State\InitException * @expectedExceptionMessage Current store is not active. */ - public function testBeforeDispatchWhenStoreNotActive() + public function testBeforeExecuteWhenStoreNotActive() { $this->_storeMock->expects($this->any())->method('isActive')->will($this->returnValue(false)); - $this->_plugin->beforeDispatch($this->subjectMock, $this->requestMock); + $this->_plugin->beforeExecute($this->subjectMock); } - public function testBeforeDispatchWhenStoreIsActive() + public function testBeforeExecuteWhenStoreIsActive() { $this->_storeMock->expects($this->any())->method('isActive')->will($this->returnValue(true)); - $result = $this->_plugin->beforeDispatch($this->subjectMock, $this->requestMock); + $result = $this->_plugin->beforeExecute($this->subjectMock); $this->assertNull($result); } } diff --git a/app/code/Magento/Store/etc/di.xml b/app/code/Magento/Store/etc/di.xml index 8f4151b8fc966..5bd8f6e2349fc 100644 --- a/app/code/Magento/Store/etc/di.xml +++ b/app/code/Magento/Store/etc/di.xml @@ -63,9 +63,11 @@ - - - + + + + + diff --git a/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php b/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php index 913fa4c46f0ae..d768e2f6092a0 100644 --- a/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php +++ b/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php @@ -6,60 +6,68 @@ namespace Magento\Tax\Model\App\Action; +use Magento\Customer\Model\Session; +use Magento\Framework\App\ActionInterface; +use Magento\Framework\App\Http\Context as HttpContext; +use Magento\Framework\Module\Manager as ModuleManager; +use Magento\PageCache\Model\Config as PageCacheConfig; +use Magento\Tax\Helper\Data as TaxHelper; +use Magento\Tax\Model\Calculation; + /** - * Class ContextPlugin + * Provides Action Context on before executing Controller Action */ class ContextPlugin { /** - * @var \Magento\Customer\Model\Session + * @var Session */ protected $customerSession; /** - * @var \Magento\Framework\App\Http\Context + * @var HttpContext */ protected $httpContext; /** - * @var \Magento\Tax\Helper\Data + * @var TaxHelper */ protected $taxHelper; /** - * @var \Magento\Tax\Model\Calculation\Proxy + * @var Calculation */ protected $taxCalculation; /** * Module manager * - * @var \Magento\Framework\Module\Manager + * @var ModuleManager */ private $moduleManager; /** * Cache config * - * @var \Magento\PageCache\Model\Config + * @var PageCacheConfig */ private $cacheConfig; /** - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Tax\Model\Calculation\Proxy $calculation - * @param \Magento\Tax\Helper\Data $taxHelper - * @param \Magento\Framework\Module\Manager $moduleManager - * @param \Magento\PageCache\Model\Config $cacheConfig + * @param Session $customerSession + * @param HttpContext $httpContext + * @param Calculation $calculation + * @param TaxHelper $taxHelper + * @param ModuleManager $moduleManager + * @param PageCacheConfig $cacheConfig */ public function __construct( - \Magento\Customer\Model\Session $customerSession, - \Magento\Framework\App\Http\Context $httpContext, - \Magento\Tax\Model\Calculation\Proxy $calculation, //phpcs:ignore Magento2.Classes.DiscouragedDependencies - \Magento\Tax\Helper\Data $taxHelper, - \Magento\Framework\Module\Manager $moduleManager, - \Magento\PageCache\Model\Config $cacheConfig + Session $customerSession, + HttpContext $httpContext, + Calculation $calculation, //phpcs:ignore Magento2.Classes.DiscouragedDependencies + TaxHelper $taxHelper, + ModuleManager $moduleManager, + PageCacheConfig $cacheConfig ) { $this->customerSession = $customerSession; $this->httpContext = $httpContext; @@ -72,15 +80,12 @@ public function __construct( /** * Before dispatch. * - * @param \Magento\Framework\App\ActionInterface $subject - * @param \Magento\Framework\App\RequestInterface $request - * @return mixed + * @param ActionInterface $subject + * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function beforeDispatch( - \Magento\Framework\App\ActionInterface $subject, - \Magento\Framework\App\RequestInterface $request - ) { + public function beforeExecute(ActionInterface $subject) + { if (!$this->customerSession->isLoggedIn() || !$this->moduleManager->isEnabled('Magento_PageCache') || !$this->cacheConfig->isEnabled() || diff --git a/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php b/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php index a6c7e9bb8685a..8601bdc175ae8 100644 --- a/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php +++ b/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php @@ -5,81 +5,105 @@ */ namespace Magento\Tax\Test\Unit\App\Action; +use Magento\Customer\Model\Session; +use Magento\Framework\App\Http\Context as HttpContext; +use Magento\Framework\App\Test\Unit\Action\Stub\ActionStub; +use Magento\Framework\Module\Manager as ModuleManager; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\PageCache\Model\Config as PageCacheConfig; +use Magento\Tax\Helper\Data as TaxHelper; +use Magento\Tax\Model\App\Action\ContextPlugin as TaxContextPlugin; +use Magento\Tax\Model\Calculation; +use Magento\Weee\Helper\Data as WeeeHelper; +use Magento\Weee\Model\Tax; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + /** - * Context plugin test + * Unit Tests to cover ContextPlugin */ -class ContextPluginTest extends \PHPUnit\Framework\TestCase +class ContextPluginTest extends TestCase { /** - * @var \Magento\Tax\Helper\Data + * @var ObjectManagerHelper + */ + private $objectManager; + + /** + * @var TaxHelper|MockObject */ protected $taxHelperMock; /** - * @var \Magento\Weee\Helper\Data + * @var WeeeHelper|MockObject */ protected $weeeHelperMock; /** - * @var \Magento\Weee\Model\Tax + * @var Tax|MockObject */ protected $weeeTaxMock; /** - * @var \Magento\Framework\App\Http\Context + * @var HttpContext|MockObject */ protected $httpContextMock; /** - * @var \Magento\Tax\Model\Calculation\Proxy + * @var Calculation|MockObject */ protected $taxCalculationMock; /** * Module manager * - * @var \Magento\Framework\Module\Manager + * @var ModuleManager|MockObject */ private $moduleManagerMock; /** * Cache config * - * @var \Magento\PageCache\Model\Config + * @var PageCacheConfig|MockObject */ private $cacheConfigMock; /** - * @var \Magento\Tax\Model\App\Action\ContextPlugin + * @var Session|MockObject + */ + private $customerSessionMock; + + /** + * @var TaxContextPlugin */ protected $contextPlugin; protected function setUp() { - $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->objectManager = new ObjectManagerHelper($this); - $this->taxHelperMock = $this->getMockBuilder(\Magento\Tax\Helper\Data::class) + $this->taxHelperMock = $this->getMockBuilder(TaxHelper::class) ->disableOriginalConstructor() ->getMock(); - $this->weeeHelperMock = $this->getMockBuilder(\Magento\Weee\Helper\Data::class) + $this->weeeHelperMock = $this->getMockBuilder(WeeeHelper::class) ->disableOriginalConstructor() ->getMock(); - $this->weeeTaxMock = $this->getMockBuilder(\Magento\Weee\Model\Tax::class) + $this->weeeTaxMock = $this->getMockBuilder(Tax::class) ->disableOriginalConstructor() ->getMock(); - $this->httpContextMock = $this->getMockBuilder(\Magento\Framework\App\Http\Context::class) + $this->httpContextMock = $this->getMockBuilder(HttpContext::class) ->disableOriginalConstructor() ->getMock(); - $this->taxCalculationMock = $this->getMockBuilder(\Magento\Tax\Model\Calculation\Proxy::class) + $this->taxCalculationMock = $this->getMockBuilder(Calculation::class) ->disableOriginalConstructor() ->setMethods(['getTaxRates']) ->getMock(); - $this->customerSessionMock = $this->getMockBuilder(\Magento\Customer\Model\Session::class) + $this->customerSessionMock = $this->getMockBuilder(Session::class) ->disableOriginalConstructor() ->setMethods( [ @@ -89,16 +113,16 @@ protected function setUp() ) ->getMock(); - $this->moduleManagerMock = $this->getMockBuilder(\Magento\Framework\Module\Manager::class) + $this->moduleManagerMock = $this->getMockBuilder(ModuleManager::class) ->disableOriginalConstructor() ->getMock(); - $this->cacheConfigMock = $this->getMockBuilder(\Magento\PageCache\Model\Config::class) + $this->cacheConfigMock = $this->getMockBuilder(PageCacheConfig::class) ->disableOriginalConstructor() ->getMock(); $this->contextPlugin = $this->objectManager->getObject( - \Magento\Tax\Model\App\Action\ContextPlugin::class, + TaxContextPlugin::class, [ 'customerSession' => $this->customerSessionMock, 'httpContext' => $this->httpContextMock, @@ -116,9 +140,9 @@ protected function setUp() * @param bool $cache * @param bool $taxEnabled * @param bool $loggedIn - * @dataProvider beforeDispatchDataProvider + * @dataProvider beforeExecuteDataProvider */ - public function testBeforeDispatch($cache, $taxEnabled, $loggedIn) + public function testBeforeExecute($cache, $taxEnabled, $loggedIn) { $this->customerSessionMock->expects($this->any()) ->method('isLoggedIn') @@ -163,9 +187,8 @@ public function testBeforeDispatch($cache, $taxEnabled, $loggedIn) ->with('tax_rates', [], 0); } - $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); - $request = $this->createPartialMock(\Magento\Framework\App\Request\Http::class, ['getActionName']); - $result = $this->contextPlugin->beforeDispatch($action, $request); + $action = $this->objectManager->getObject(ActionStub::class); + $result = $this->contextPlugin->beforeExecute($action); $this->assertNull($result); } else { $this->assertFalse($loggedIn); @@ -175,7 +198,7 @@ public function testBeforeDispatch($cache, $taxEnabled, $loggedIn) /** * @return array */ - public function beforeDispatchDataProvider() + public function beforeExecuteDataProvider() { return [ [false, false, false], diff --git a/app/code/Magento/Tax/etc/frontend/di.xml b/app/code/Magento/Tax/etc/frontend/di.xml index 4db3f54b0edd9..d1b8d93e96935 100644 --- a/app/code/Magento/Tax/etc/frontend/di.xml +++ b/app/code/Magento/Tax/etc/frontend/di.xml @@ -35,7 +35,7 @@ - + diff --git a/app/code/Magento/Theme/Model/Theme/Plugin/Registration.php b/app/code/Magento/Theme/Model/Theme/Plugin/Registration.php index 05030c56c2ee0..13102a722eddf 100644 --- a/app/code/Magento/Theme/Model/Theme/Plugin/Registration.php +++ b/app/code/Magento/Theme/Model/Theme/Plugin/Registration.php @@ -5,8 +5,7 @@ */ namespace Magento\Theme\Model\Theme\Plugin; -use Magento\Backend\App\AbstractAction; -use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\ActionInterface; use Magento\Theme\Model\Theme\Registration as ThemeRegistration; use Magento\Framework\Exception\LocalizedException; use Psr\Log\LoggerInterface; @@ -16,32 +15,34 @@ use Magento\Framework\Config\Theme; /** + * Plugin for Theme Registration + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Registration { /** - * @var \Magento\Theme\Model\Theme\Registration + * @var ThemeRegistration */ protected $themeRegistration; /** - * @var \Magento\Theme\Model\Theme\Collection + * @var ThemeCollection */ protected $themeCollection; /** - * @var \Magento\Theme\Model\ResourceModel\Theme\Collection + * @var ThemeLoader */ protected $themeLoader; /** - * @var \Psr\Log\LoggerInterface + * @var LoggerInterface */ protected $logger; /** - * @var \Magento\Framework\App\State + * @var AppState */ protected $appState; @@ -69,15 +70,13 @@ public function __construct( /** * Add new theme from filesystem and update existing * - * @param AbstractAction $subject - * @param RequestInterface $request + * @param ActionInterface $subject * * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function beforeDispatch( - AbstractAction $subject, - RequestInterface $request + public function beforeExecute( + ActionInterface $subject ) { try { if ($this->appState->getMode() != AppState::MODE_PRODUCTION) { diff --git a/app/code/Magento/Theme/Test/Unit/Model/Theme/Plugin/RegistrationTest.php b/app/code/Magento/Theme/Test/Unit/Model/Theme/Plugin/RegistrationTest.php index 190a6edf55900..fb320de97dcc8 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Theme/Plugin/RegistrationTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Theme/Plugin/RegistrationTest.php @@ -3,73 +3,89 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Theme\Test\Unit\Model\Theme\Plugin; -use Magento\Theme\Model\Theme\Plugin\Registration; +use Magento\Framework\App\ActionInterface; +use Magento\Framework\App\State; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Theme\Model\ResourceModel\Theme\Collection as ThemeCollectionResourceModel; +use Magento\Theme\Model\Theme; +use Magento\Theme\Model\Theme\Collection as ThemeCollection; +use Magento\Theme\Model\Theme\Plugin\Registration as RegistrationPlugin; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; +use Magento\Theme\Model\Theme\Registration as ThemeRegistration; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; class RegistrationTest extends \PHPUnit\Framework\TestCase { - /** @var \Magento\Theme\Model\Theme\Registration|\PHPUnit_Framework_MockObject_MockObject */ - protected $themeRegistration; - - /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $logger; + /** + * @var ThemeRegistration|MockObject + */ + protected $themeRegistrationMock; - /** @var \Magento\Backend\App\AbstractAction|\PHPUnit_Framework_MockObject_MockObject */ - protected $abstractAction; + /** + * @var LoggerInterface|MockObject + */ + protected $loggerMock; - /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $request; + /** + * @var ActionInterface|MockObject + */ + protected $actionMock; - /** @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject */ - protected $appState; + /** + * @var State|MockObject + */ + protected $appStateMock; - /** @var \Magento\Theme\Model\Theme\Collection|\PHPUnit_Framework_MockObject_MockObject */ - protected $themeCollection; + /** + * @var ThemeCollection|MockObject + */ + protected $themeCollectionMock; - /** @var \Magento\Theme\Model\ResourceModel\Theme\Collection|\PHPUnit_Framework_MockObject_MockObject */ - protected $themeLoader; + /** + * @var ThemeCollectionResourceModel|MockObject + */ + protected $themeLoaderMock; - /** @var Registration */ + /** + * @var RegistrationPlugin + */ protected $plugin; protected function setUp() { - $this->themeRegistration = $this->createMock(\Magento\Theme\Model\Theme\Registration::class); - $this->logger = $this->getMockForAbstractClass(\Psr\Log\LoggerInterface::class, [], '', false); - $this->abstractAction = $this->getMockForAbstractClass( - \Magento\Backend\App\AbstractAction::class, - [], - '', - false - ); - $this->request = $this->getMockForAbstractClass(\Magento\Framework\App\RequestInterface::class, [], '', false); - $this->appState = $this->createMock(\Magento\Framework\App\State::class); - $this->themeCollection = $this->createMock(\Magento\Theme\Model\Theme\Collection::class); - $this->themeLoader = $this->createMock(\Magento\Theme\Model\ResourceModel\Theme\Collection::class); - $this->plugin = new Registration( - $this->themeRegistration, - $this->themeCollection, - $this->themeLoader, - $this->logger, - $this->appState - ); + $this->themeRegistrationMock = $this->createMock(ThemeRegistration::class); + $this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class, [], '', false); + $this->actionMock = $this->createMock(ActionInterface::class); + $this->appStateMock = $this->createMock(State::class); + $this->themeCollectionMock = $this->createMock(ThemeCollection::class); + $this->themeLoaderMock = $this->createMock(ThemeCollectionResourceModel::class); + + $objectManager = new ObjectManager($this); + $this->plugin = $objectManager->getObject(RegistrationPlugin::class, [ + 'themeRegistration' => $this->themeRegistrationMock, + 'themeCollection' => $this->themeCollectionMock, + 'themeLoader' => $this->themeLoaderMock, + 'logger' => $this->loggerMock, + 'appState' => $this->appStateMock + ]); } /** * @param bool $hasParentTheme - * @dataProvider dataProviderBeforeDispatch + * @dataProvider dataProviderBeforeExecute * @SuppressWarnings(PHPMD.NPathComplexity) */ - public function testBeforeDispatch( - $hasParentTheme - ) { + public function testBeforeExecute($hasParentTheme) + { $themeId = 1; $themeTitle = 'Theme title'; - $themeFromConfigMock = $this->getMockBuilder(\Magento\Theme\Model\Theme::class) + $themeFromConfigMock = $this->getMockBuilder(Theme::class) ->disableOriginalConstructor() ->setMethods([ 'getArea', @@ -79,7 +95,7 @@ public function testBeforeDispatch( ]) ->getMock(); - $themeFromDbMock = $this->getMockBuilder(\Magento\Theme\Model\Theme::class) + $themeFromDbMock = $this->getMockBuilder(Theme::class) ->disableOriginalConstructor() ->setMethods([ 'setParentId', @@ -88,26 +104,26 @@ public function testBeforeDispatch( ]) ->getMock(); - $parentThemeFromDbMock = $this->getMockBuilder(\Magento\Theme\Model\Theme::class) + $parentThemeFromDbMock = $this->getMockBuilder(Theme::class) ->disableOriginalConstructor() ->getMock(); - $parentThemeFromConfigMock = $this->getMockBuilder(\Magento\Theme\Model\Theme::class) + $parentThemeFromConfigMock = $this->getMockBuilder(Theme::class) ->disableOriginalConstructor() ->getMock(); - $this->appState->expects($this->once()) + $this->appStateMock->expects($this->once()) ->method('getMode') ->willReturn('default'); - $this->themeRegistration->expects($this->once()) + $this->themeRegistrationMock->expects($this->once()) ->method('register'); - $this->themeCollection->expects($this->once()) + $this->themeCollectionMock->expects($this->once()) ->method('loadData') ->willReturn([$themeFromConfigMock]); - $this->themeLoader->expects($hasParentTheme ? $this->exactly(2) : $this->once()) + $this->themeLoaderMock->expects($hasParentTheme ? $this->exactly(2) : $this->once()) ->method('getThemeByFullPath') ->willReturnMap([ ['frontend/Magento/blank', $parentThemeFromDbMock], @@ -147,13 +163,13 @@ public function testBeforeDispatch( ->method('save') ->willReturnSelf(); - $this->plugin->beforeDispatch($this->abstractAction, $this->request); + $this->plugin->beforeExecute($this->actionMock); } /** * @return array */ - public function dataProviderBeforeDispatch() + public function dataProviderBeforeExecute() { return [ [true], @@ -163,16 +179,16 @@ public function dataProviderBeforeDispatch() public function testBeforeDispatchWithProductionMode() { - $this->appState->expects($this->once())->method('getMode')->willReturn('production'); - $this->plugin->beforeDispatch($this->abstractAction, $this->request); + $this->appStateMock->expects($this->once())->method('getMode')->willReturn('production'); + $this->plugin->beforeExecute($this->actionMock); } public function testBeforeDispatchWithException() { $exception = new LocalizedException(new Phrase('Phrase')); - $this->themeRegistration->expects($this->once())->method('register')->willThrowException($exception); - $this->logger->expects($this->once())->method('critical'); + $this->themeRegistrationMock->expects($this->once())->method('register')->willThrowException($exception); + $this->loggerMock->expects($this->once())->method('critical'); - $this->plugin->beforeDispatch($this->abstractAction, $this->request); + $this->plugin->beforeExecute($this->actionMock); } } diff --git a/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php b/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php index aae6f769eb500..66485d0410872 100644 --- a/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php +++ b/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php @@ -6,78 +6,92 @@ namespace Magento\Weee\Model\App\Action; +use Magento\Customer\Model\Session as CustomerSession; +use Magento\Framework\App\ActionInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\Http\Context as HttpContext; +use Magento\Framework\Module\Manager as ModuleManager; +use Magento\PageCache\Model\Config as PageCacheConfig; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Tax\Helper\Data as TaxHelper; +use Magento\Tax\Model\Config as TaxConfig; +use Magento\Weee\Helper\Data as WeeeHelper; +use Magento\Weee\Model\Tax; + /** - * Class ContextPlugin + * Plugin to provide Context information to Weee Action + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ContextPlugin { /** - * @var \Magento\Customer\Model\Session + * @var CustomerSession */ protected $customerSession; /** - * @var \Magento\Framework\App\Http\Context + * @var HttpContext */ protected $httpContext; /** - * @var \Magento\Tax\Helper\Data + * @var TaxHelper */ protected $taxHelper; /** - * @var \Magento\Weee\Helper\Data + * @var WeeeHelper */ protected $weeeHelper; /** - * @var \Magento\Framework\Module\Manager + * @var ModuleManager */ protected $moduleManager; /** - * @var \Magento\Weee\Model\Tax + * @var Tax */ protected $weeeTax; /** - * @var \Magento\PageCache\Model\Config + * @var PageCacheConfig */ protected $cacheConfig; /** - * @var \Magento\Store\Model\StoreManagerInterface + * @var StoreManagerInterface */ protected $storeManager; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface */ protected $scopeConfig; /** - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Weee\Model\Tax $weeeTax - * @param \Magento\Tax\Helper\Data $taxHelper - * @param \Magento\Weee\Helper\Data $weeeHelper - * @param \Magento\Framework\Module\Manager $moduleManager - * @param \Magento\PageCache\Model\Config $cacheConfig - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param CustomerSession $customerSession + * @param HttpContext $httpContext + * @param Tax $weeeTax + * @param TaxHelper $taxHelper + * @param WeeeHelper $weeeHelper + * @param ModuleManager $moduleManager + * @param PageCacheConfig $cacheConfig + * @param StoreManagerInterface $storeManager + * @param ScopeConfigInterface $scopeConfig */ public function __construct( - \Magento\Customer\Model\Session $customerSession, - \Magento\Framework\App\Http\Context $httpContext, - \Magento\Weee\Model\Tax $weeeTax, - \Magento\Tax\Helper\Data $taxHelper, - \Magento\Weee\Helper\Data $weeeHelper, - \Magento\Framework\Module\Manager $moduleManager, - \Magento\PageCache\Model\Config $cacheConfig, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + CustomerSession $customerSession, + HttpContext $httpContext, + Tax $weeeTax, + TaxHelper $taxHelper, + WeeeHelper $weeeHelper, + ModuleManager $moduleManager, + PageCacheConfig $cacheConfig, + StoreManagerInterface $storeManager, + ScopeConfigInterface $scopeConfig ) { $this->customerSession = $customerSession; $this->httpContext = $httpContext; @@ -93,18 +107,15 @@ public function __construct( /** * Before dispatch. * - * @param \Magento\Framework\App\ActionInterface $subject - * @param \Magento\Framework\App\RequestInterface $request + * @param ActionInterface $subject * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function beforeDispatch( - \Magento\Framework\App\ActionInterface $subject, - \Magento\Framework\App\RequestInterface $request - ) { + public function beforeExecute(ActionInterface $subject) + { if (!$this->weeeHelper->isEnabled() || !$this->customerSession->isLoggedIn() || !$this->moduleManager->isEnabled('Magento_PageCache') || @@ -128,26 +139,14 @@ public function beforeDispatch( } elseif ($countryId && !$regionId) { // country exist and region does not exist $regionId = 0; - $exist = $this->weeeTax->isWeeeInLocation( - $countryId, - $regionId, - $websiteId - ); + $exist = $this->weeeTax->isWeeeInLocation($countryId, $regionId, $websiteId); } else { // country and region exist - $exist = $this->weeeTax->isWeeeInLocation( - $countryId, - $regionId, - $websiteId - ); + $exist = $this->weeeTax->isWeeeInLocation($countryId, $regionId, $websiteId); if (!$exist) { // just check the country for weee $regionId = 0; - $exist = $this->weeeTax->isWeeeInLocation( - $countryId, - $regionId, - $websiteId - ); + $exist = $this->weeeTax->isWeeeInLocation($countryId, $regionId, $websiteId); } } @@ -171,13 +170,13 @@ protected function getWeeeTaxRegion($basedOn) $countryId = null; $regionId = null; $defaultCountryId = $this->scopeConfig->getValue( - \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_COUNTRY, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + TaxConfig::CONFIG_XML_PATH_DEFAULT_COUNTRY, + ScopeInterface::SCOPE_STORE, null ); $defaultRegionId = $this->scopeConfig->getValue( - \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + TaxConfig::CONFIG_XML_PATH_DEFAULT_REGION, + ScopeInterface::SCOPE_STORE, null ); diff --git a/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php b/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php index c829b524527a6..b28a223ef2dce 100644 --- a/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php +++ b/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php @@ -3,114 +3,146 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Weee\Test\Unit\App\Action; +use Magento\Customer\Model\Session as CustomerSession; +use Magento\Framework\App\Config; +use Magento\Framework\App\Http\Context as HttpContext; +use Magento\Framework\App\Test\Unit\Action\Stub\ActionStub; +use Magento\Framework\Module\Manager as ModuleManager; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\PageCache\Model\Config as PageCacheConfig; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManager; +use Magento\Tax\Helper\Data as TaxHelper; +use Magento\Tax\Model\Calculation\Proxy as TaxCalculation; +use Magento\Tax\Model\Config as TaxConfig; +use Magento\Weee\Helper\Data as WeeeHelper; +use Magento\Weee\Model\App\Action\ContextPlugin; +use Magento\Weee\Model\Tax; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + /** - * Class ContextPluginTest + * Unit Tests to cover Context Plugin * - * @package Magento\Weee\Test\Unit\App\Action * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class ContextPluginTest extends \PHPUnit\Framework\TestCase +class ContextPluginTest extends TestCase { /** - * @var \Magento\Tax\Helper\Data + * @var TaxHelper|MockObject */ protected $taxHelperMock; /** - * @var \Magento\Weee\Helper\Data + * @var WeeeHelper|MockObject */ protected $weeeHelperMock; /** - * @var \Magento\Weee\Model\Tax + * @var Tax|MockObject */ protected $weeeTaxMock; /** - * @var \Magento\Framework\App\Http\Context + * @var HttpContext|MockObject */ protected $httpContextMock; /** - * @var \Magento\Tax\Model\Calculation\Proxy + * @var TaxCalculation|MockObject */ protected $taxCalculationMock; /** - * @var \Magento\Framework\Module\Manager + * @var ModuleManager|MockObject */ protected $moduleManagerMock; /** - * @var \Magento\PageCache\Model\Config + * @var PageCacheConfig|MockObject */ protected $cacheConfigMock; /** - * @var \Magento\Store\Model\StoreManager + * @var StoreManager|MockObject */ - protected $storeManageMock; + protected $storeManagerMock; /** - * @var \Magento\Framework\App\Config\ScopeConfig + * @var Config|MockObject */ protected $scopeConfigMock; /** - * @var \Magento\Tax\Model\App\Action\ContextPlugin + * @var CustomerSession|MockObject + */ + private $customerSessionMock; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var ContextPlugin */ protected $contextPlugin; protected function setUp() { - $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->objectManager = new ObjectManager($this); - $this->taxHelperMock = $this->getMockBuilder(\Magento\Tax\Helper\Data::class) + $this->taxHelperMock = $this->getMockBuilder(TaxHelper::class) ->disableOriginalConstructor() ->getMock(); - $this->weeeHelperMock = $this->getMockBuilder(\Magento\Weee\Helper\Data::class) + $this->weeeHelperMock = $this->getMockBuilder(WeeeHelper::class) ->disableOriginalConstructor() ->getMock(); - $this->weeeTaxMock = $this->getMockBuilder(\Magento\Weee\Model\Tax::class) + $this->weeeTaxMock = $this->getMockBuilder(Tax::class) ->disableOriginalConstructor() ->getMock(); - $this->httpContextMock = $this->getMockBuilder(\Magento\Framework\App\Http\Context::class) + $this->httpContextMock = $this->getMockBuilder(HttpContext::class) ->disableOriginalConstructor() ->getMock(); - $this->customerSessionMock = $this->getMockBuilder(\Magento\Customer\Model\Session::class) + $this->customerSessionMock = $this->getMockBuilder(CustomerSession::class) ->disableOriginalConstructor() ->setMethods( [ - 'getDefaultTaxBillingAddress', 'getDefaultTaxShippingAddress', 'getCustomerTaxClassId', - 'getWebsiteId', 'isLoggedIn' + 'getDefaultTaxBillingAddress', + 'getDefaultTaxShippingAddress', + 'getCustomerTaxClassId', + 'getWebsiteId', + 'isLoggedIn' ] ) ->getMock(); - $this->moduleManagerMock = $this->getMockBuilder(\Magento\Framework\Module\Manager::class) + $this->moduleManagerMock = $this->getMockBuilder(ModuleManager::class) ->disableOriginalConstructor() ->getMock(); - $this->cacheConfigMock = $this->getMockBuilder(\Magento\PageCache\Model\Config::class) + $this->cacheConfigMock = $this->getMockBuilder(PageCacheConfig::class) ->disableOriginalConstructor() ->getMock(); - $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManager::class) + $this->storeManagerMock = $this->getMockBuilder(StoreManager::class) ->disableOriginalConstructor() ->getMock(); - $this->scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config::class) + $this->scopeConfigMock = $this->getMockBuilder(Config::class) ->disableOriginalConstructor() ->getMock(); $this->contextPlugin = $this->objectManager->getObject( - \Magento\Weee\Model\App\Action\ContextPlugin::class, + ContextPlugin::class, [ 'customerSession' => $this->customerSessionMock, 'httpContext' => $this->httpContextMock, @@ -125,7 +157,7 @@ protected function setUp() ); } - public function testBeforeDispatchBasedOnDefault() + public function testBeforeExecuteBasedOnDefault() { $this->customerSessionMock->expects($this->once()) ->method('isLoggedIn') @@ -148,7 +180,7 @@ public function testBeforeDispatchBasedOnDefault() ->method('getTaxBasedOn') ->willReturn('billing'); - $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + $storeMock = $this->getMockBuilder(Store::class) ->disableOriginalConstructor() ->getMock(); @@ -163,8 +195,8 @@ public function testBeforeDispatchBasedOnDefault() $this->scopeConfigMock->expects($this->at(0)) ->method('getValue') ->with( - \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_COUNTRY, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + TaxConfig::CONFIG_XML_PATH_DEFAULT_COUNTRY, + ScopeInterface::SCOPE_STORE, null ) ->willReturn('US'); @@ -172,8 +204,8 @@ public function testBeforeDispatchBasedOnDefault() $this->scopeConfigMock->expects($this->at(1)) ->method('getValue') ->with( - \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + TaxConfig::CONFIG_XML_PATH_DEFAULT_REGION, + ScopeInterface::SCOPE_STORE, null ) ->willReturn(0); @@ -187,13 +219,13 @@ public function testBeforeDispatchBasedOnDefault() ->method('setValue') ->with('weee_tax_region', ['countryId' => 'US', 'regionId' => 0], 0); - $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); - $request = $this->createPartialMock(\Magento\Framework\App\Request\Http::class, ['getActionName']); + /** @var ActionStub $action */ + $action = $this->objectManager->getObject(ActionStub::class); - $this->contextPlugin->beforeDispatch($action, $request); + $this->contextPlugin->beforeExecute($action); } - public function testBeforeDispatchBasedOnOrigin() + public function testBeforeExecuteBasedOnOrigin() { $this->customerSessionMock->expects($this->once()) ->method('isLoggedIn') @@ -216,13 +248,13 @@ public function testBeforeDispatchBasedOnOrigin() ->method('getTaxBasedOn') ->willReturn('origin'); - $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); - $request = $this->createPartialMock(\Magento\Framework\App\Request\Http::class, ['getActionName']); + /** @var ActionStub $action */ + $action = $this->objectManager->getObject(ActionStub::class); - $this->contextPlugin->beforeDispatch($action, $request); + $this->contextPlugin->beforeExecute($action); } - public function testBeforeDispatchBasedOnBilling() + public function testBeforeExecuteBasedOnBilling() { $this->customerSessionMock->expects($this->once()) ->method('isLoggedIn') @@ -245,7 +277,7 @@ public function testBeforeDispatchBasedOnBilling() ->method('getTaxBasedOn') ->willReturn('billing'); - $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + $storeMock = $this->getMockBuilder(Store::class) ->disableOriginalConstructor() ->getMock(); @@ -260,8 +292,8 @@ public function testBeforeDispatchBasedOnBilling() $this->scopeConfigMock->expects($this->at(0)) ->method('getValue') ->with( - \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_COUNTRY, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + TaxConfig::CONFIG_XML_PATH_DEFAULT_COUNTRY, + ScopeInterface::SCOPE_STORE, null ) ->willReturn('US'); @@ -269,8 +301,8 @@ public function testBeforeDispatchBasedOnBilling() $this->scopeConfigMock->expects($this->at(1)) ->method('getValue') ->with( - \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + TaxConfig::CONFIG_XML_PATH_DEFAULT_REGION, + ScopeInterface::SCOPE_STORE, null ) ->willReturn(0); @@ -288,13 +320,13 @@ public function testBeforeDispatchBasedOnBilling() ->method('setValue') ->with('weee_tax_region', ['countryId' => 'US', 'regionId' => 1], 0); - $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); - $request = $this->createPartialMock(\Magento\Framework\App\Request\Http::class, ['getActionName']); + /** @var ActionStub $action */ + $action = $this->objectManager->getObject(ActionStub::class); - $this->contextPlugin->beforeDispatch($action, $request); + $this->contextPlugin->beforeExecute($action); } - public function testBeforeDispatchBasedOnShipping() + public function testBeforeExecuterBasedOnShipping() { $this->customerSessionMock->expects($this->once()) ->method('isLoggedIn') @@ -317,7 +349,7 @@ public function testBeforeDispatchBasedOnShipping() ->method('getTaxBasedOn') ->willReturn('shipping'); - $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + $storeMock = $this->getMockBuilder(Store::class) ->disableOriginalConstructor() ->getMock(); @@ -332,8 +364,8 @@ public function testBeforeDispatchBasedOnShipping() $this->scopeConfigMock->expects($this->at(0)) ->method('getValue') ->with( - \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_COUNTRY, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + TaxConfig::CONFIG_XML_PATH_DEFAULT_COUNTRY, + ScopeInterface::SCOPE_STORE, null ) ->willReturn('US'); @@ -341,8 +373,8 @@ public function testBeforeDispatchBasedOnShipping() $this->scopeConfigMock->expects($this->at(1)) ->method('getValue') ->with( - \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + TaxConfig::CONFIG_XML_PATH_DEFAULT_REGION, + ScopeInterface::SCOPE_STORE, null ) ->willReturn(0); @@ -360,9 +392,9 @@ public function testBeforeDispatchBasedOnShipping() ->method('setValue') ->with('weee_tax_region', ['countryId' => 'US', 'regionId' => 1], 0); - $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); - $request = $this->createPartialMock(\Magento\Framework\App\Request\Http::class, ['getActionName']); + /** @var ActionStub $action */ + $action = $this->objectManager->getObject(ActionStub::class); - $this->contextPlugin->beforeDispatch($action, $request); + $this->contextPlugin->beforeExecute($action); } } diff --git a/app/code/Magento/Weee/etc/frontend/di.xml b/app/code/Magento/Weee/etc/frontend/di.xml index 1ce09205b6e77..f6417fd86a3e1 100644 --- a/app/code/Magento/Weee/etc/frontend/di.xml +++ b/app/code/Magento/Weee/etc/frontend/di.xml @@ -13,7 +13,7 @@ - + diff --git a/dev/tests/integration/testsuite/Magento/Authorizenet/Controller/Adminhtml/Authorizenet/Directpost/Payment/PlaceTest.php b/dev/tests/integration/testsuite/Magento/Authorizenet/Controller/Adminhtml/Authorizenet/Directpost/Payment/PlaceTest.php index 35892623ef7af..1b8b1b716ce5f 100644 --- a/dev/tests/integration/testsuite/Magento/Authorizenet/Controller/Adminhtml/Authorizenet/Directpost/Payment/PlaceTest.php +++ b/dev/tests/integration/testsuite/Magento/Authorizenet/Controller/Adminhtml/Authorizenet/Directpost/Payment/PlaceTest.php @@ -3,17 +3,34 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Authorizenet\Controller\Adminhtml\Authorizenet\Directpost\Payment; +use Magento\Authorizenet\Model\Directpost; +use Magento\Backend\App\Action\Context as BackendActionContext; +use Magento\Backend\Model\Session\Quote as SessionQuote; +use Magento\Backend\Model\UrlInterface; +use Magento\Framework\Json\Helper\Data as JsonHelper; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Payment; +use Magento\Sales\Model\AdminOrder\Create as AdminOrderCreate; +use Magento\Sales\Model\Order; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\AbstractBackendController; +use PHPUnit\Framework\MockObject\MockObject; + /** - * Class PlaceTest + * Verify AuthorizeNet Controller for PlaceOrder * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class PlaceTest extends \Magento\TestFramework\TestCase\AbstractBackendController +class PlaceTest extends AbstractBackendController { /** * Test requestToAuthorizenetData returning + * @magentoAppArea adminhtml */ public function testExecuteAuthorizenetDataReturning() { @@ -22,44 +39,44 @@ public function testExecuteAuthorizenetDataReturning() $this->getRequest()->setParam('payment', ['method' => 'authorizenet_directpost']); $this->getRequest()->setParam('controller', 'order_create'); $orderCreateMock = $this->getOrderCreateMock($requestToAuthorizenetData); - $directpostMock = $this->getMockBuilder(\Magento\Authorizenet\Model\Directpost::class) + $directpostMock = $this->getMockBuilder(Directpost::class) ->setMethods(['getCode']) ->disableOriginalConstructor() ->getMock(); $directpostMock->expects($this->once()) ->method('getCode') ->willReturn('authorizenet_directpost'); - $jsonHelper = $this->_objectManager->get(\Magento\Framework\Json\Helper\Data::class); - $objectManagerMock = $this->getMockBuilder(\Magento\Framework\ObjectManagerInterface::class) + $jsonHelper = $this->_objectManager->get(JsonHelper::class); + $objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class) ->setMethods(['create', 'get']) ->getMockForAbstractClass(); $objectManagerMock->expects($this->atLeastOnce()) ->method('create') - ->with(\Magento\Authorizenet\Model\Directpost::class) + ->with(Directpost::class) ->willReturn($directpostMock); - $authorizenetSessionMock = $this->getMockBuilder(\Magento\Authorizenet\Model\Directpost::class) + $authorizenetSessionMock = $this->getMockBuilder(Directpost::class) ->disableOriginalConstructor() ->getMock(); - $urlMock = $this->getMockBuilder(\Magento\Backend\Model\UrlInterface::class) + $urlMock = $this->getMockBuilder(UrlInterface::class) ->getMockForAbstractClass(); $objectManagerMock->expects($this->atLeastOnce()) ->method('get') ->willReturnMap([ - [\Magento\Sales\Model\AdminOrder\Create::class, $orderCreateMock], - [\Magento\Framework\Json\Helper\Data::class, $jsonHelper], - [\Magento\Authorizenet\Model\Directpost\Session::class, $authorizenetSessionMock], - [\Magento\Backend\Model\UrlInterface::class, $urlMock], + [AdminOrderCreate::class, $orderCreateMock], + [JsonHelper::class, $jsonHelper], + [Directpost\Session::class, $authorizenetSessionMock], + [UrlInterface::class, $urlMock], ]); - $context = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Backend\App\Action\Context::class, + $context = $this->getObjectManager()->create( + BackendActionContext::class, [ 'objectManager' => $objectManagerMock ] ); - $controller = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Authorizenet\Controller\Adminhtml\Authorizenet\Directpost\Payment\PlaceTesting::class, + $controller = $this->getObjectManager()->create( + PlaceTesting::class, ['context' => $context] ); $controller->execute(); @@ -68,14 +85,14 @@ public function testExecuteAuthorizenetDataReturning() /** * @param array $requestToAuthorizenetData - * @return \PHPUnit_Framework_MockObject_MockObject + * @return AdminOrderCreate|MockObject */ private function getOrderCreateMock($requestToAuthorizenetData) { - $methodInstanceMock = $this->getMockBuilder(\Magento\Authorizenet\Model\Directpost::class) + $methodInstanceMock = $this->getMockBuilder(Directpost::class) ->disableOriginalConstructor() ->getMock(); - $directpostRequestMock = $this->getMockBuilder(\Magento\Authorizenet\Model\Directpost\Request::class) + $directpostRequestMock = $this->getMockBuilder(Directpost\Request::class) ->setMethods(['getData']) ->disableOriginalConstructor() ->getMock(); @@ -85,7 +102,7 @@ private function getOrderCreateMock($requestToAuthorizenetData) $methodInstanceMock->expects($this->once()) ->method('generateRequestFromOrder') ->willReturn($directpostRequestMock); - $paymentMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Payment::class) + $paymentMock = $this->getMockBuilder(Payment::class) ->setMethods(['getMethod', 'getMethodInstance']) ->disableOriginalConstructor() ->getMock(); @@ -95,28 +112,28 @@ private function getOrderCreateMock($requestToAuthorizenetData) $paymentMock->expects($this->once()) ->method('getMethodInstance') ->willReturn($methodInstanceMock); - $quoteMock = $this->getMockBuilder(\Magento\Quote\Model\Quote::class) + $quoteMock = $this->getMockBuilder(Quote::class) ->setMethods(['getPayment', 'getStoreId']) ->disableOriginalConstructor() ->getMock(); $quoteMock->expects($this->any()) ->method('getPayment') ->willReturn($paymentMock); - $orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class) + $orderMock = $this->getMockBuilder(Order::class) ->setMethods(['getPayment']) ->disableOriginalConstructor() ->getMock(); $orderMock->expects($this->any()) ->method('getPayment') ->willReturn($paymentMock); - $sessionQuoteMock = $this->getMockBuilder(\Magento\Backend\Model\Session\Quote::class) + $sessionQuoteMock = $this->getMockBuilder(SessionQuote::class) ->setMethods(['getOrder']) ->disableOriginalConstructor() ->getMock(); $sessionQuoteMock->expects($this->once()) ->method('getOrder') ->willReturn($orderMock); - $orderCreateMock = $this->getMockBuilder(\Magento\Sales\Model\AdminOrder\Create::class) + $orderCreateMock = $this->getMockBuilder(AdminOrderCreate::class) ->setMethods(['getQuote', 'getSession', 'setIsValidate', 'importPostData', 'createOrder', 'setPaymentData']) ->disableOriginalConstructor() ->getMock(); @@ -138,4 +155,12 @@ private function getOrderCreateMock($requestToAuthorizenetData) return $orderCreateMock; } + + /** + * @return ObjectManagerInterface + */ + private function getObjectManager(): ObjectManagerInterface + { + return Bootstrap::getObjectManager(); + } } diff --git a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFilesTest.php b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFilesTest.php index c135a89a00bc7..15bd56f86486c 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFilesTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFilesTest.php @@ -10,6 +10,8 @@ /** * Test for \Magento\Cms\Controller\Adminhtml\Wysiwyg\Images\DeleteFiles class. + * + * @magentoAppArea adminhtml */ class DeleteFilesTest extends \PHPUnit\Framework\TestCase { diff --git a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFolderTest.php b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFolderTest.php index af495841b9672..94638f3a71537 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFolderTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFolderTest.php @@ -11,6 +11,8 @@ /** * Test for \Magento\Cms\Controller\Adminhtml\Wysiwyg\Images\DeleteFolder class. + * + * @magentoAppArea adminhtml */ class DeleteFolderTest extends \PHPUnit\Framework\TestCase { diff --git a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/NewFolderTest.php b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/NewFolderTest.php index e509737a0020f..4a572f8cdf228 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/NewFolderTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/NewFolderTest.php @@ -10,6 +10,8 @@ /** * Test for \Magento\Cms\Controller\Adminhtml\Wysiwyg\Images\NewFolder class. + * + * @magentoAppArea adminhtml */ class NewFolderTest extends \PHPUnit\Framework\TestCase { diff --git a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/UploadTest.php b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/UploadTest.php index 9303a5eac7868..df8994c1a5a91 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/UploadTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/UploadTest.php @@ -15,6 +15,8 @@ /** * Test for \Magento\Cms\Controller\Adminhtml\Wysiwyg\Images\Upload class. + * + * @magentoAppArea adminhtml */ class UploadTest extends \PHPUnit\Framework\TestCase { diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/ControllerActionTest.php b/dev/tests/integration/testsuite/Magento/Framework/App/ControllerActionTest.php new file mode 100644 index 0000000000000..12be7607e1872 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/ControllerActionTest.php @@ -0,0 +1,207 @@ +create(Event\ManagerInterface::class); + $eventManagerSpy = new class($originalEventManager) implements Event\ManagerInterface { + /** + * @var Event\ManagerInterface + */ + private $delegate; + + /** + * @var array[]; + */ + private $dispatchedEvents = []; + + public function __construct(Event\ManagerInterface $delegate) + { + $this->delegate = $delegate; + } + + public function dispatch($eventName, array $data = []) + { + $this->dispatchedEvents[$eventName][] = [$eventName, $data]; + $this->delegate->dispatch($eventName, $data); + } + + public function spyOnDispatchedEvent(string $eventName): array + { + return $this->dispatchedEvents[$eventName] ?? []; + } + }; + + $objectManager->addSharedInstance($eventManagerSpy, get_class($originalEventManager)); + } + + private function assertEventDispatchCount($eventName, $expectedCount) + { + $message = sprintf('Event %s was expected to be dispatched %d time(s).', $eventName, $expectedCount); + $this->assertCount($expectedCount, $this->getEventManager()->spyOnDispatchedEvent($eventName), $message); + } + + /** + * @return TestHttpRequest + */ + private function getRequest(): RequestInterface + { + return ObjectManager::getInstance()->get(TestHttpRequest::class); + } + + private function fakeAuthenticatedBackendRequest() + { + $objectManager = ObjectManager::getInstance(); + $objectManager->get(BackendUrl::class)->turnOffSecretKey(); + + $auth = $objectManager->get(BackendAuth::class); + $auth->login(TestFramework::ADMIN_NAME, TestFramework::ADMIN_PASSWORD); + } + + private function configureRequestForAction(string $route, string $actionPath, string $actionName) + { + $request = $this->getRequest(); + + $request->setRouteName($route); + $request->setControllerName($actionPath); + $request->setActionName($actionName); + $request->setDispatched(); + } + + private function getEventManager(): Event\ManagerInterface + { + return ObjectManager::getInstance()->get(Event\ManagerInterface::class); + } + + private function assertPreAndPostDispatchEventsAreDispatched() + { + $this->assertEventDispatchCount('controller_action_predispatch', 1); + $this->assertEventDispatchCount('controller_action_predispatch_testroute', 1); + $this->assertEventDispatchCount('controller_action_predispatch_testroute_actionpath_actionname', 1); + $this->assertEventDispatchCount('controller_action_postdispatch_testroute_actionpath_actionname', 1); + $this->assertEventDispatchCount('controller_action_postdispatch_testroute', 1); + $this->assertEventDispatchCount('controller_action_postdispatch', 1); + } + + /** + * @magentoAppArea frontend + */ + public function testInheritanceBasedFrontendActionDispatchesEvents() + { + $this->setupEventManagerSpy(); + + /** @var InheritanceBasedFrontendAction $action */ + $action = ObjectManager::getInstance()->create(InheritanceBasedFrontendAction::class); + $this->configureRequestForAction('testroute', 'actionpath', 'actionname'); + + $action->dispatch($this->getRequest()); + + $this->assertPreAndPostDispatchEventsAreDispatched(); + } + + /** + * @magentoAppArea frontend + */ + public function testInterfaceOnlyFrontendActionDispatchesEvents() + { + $this->setupEventManagerSpy(); + + /** @var InterfaceOnlyFrontendAction $action */ + $action = ObjectManager::getInstance()->create(InterfaceOnlyFrontendAction::class); + $this->configureRequestForAction('testroute', 'actionpath', 'actionname'); + + $action->execute(); + + $this->assertPreAndPostDispatchEventsAreDispatched(); + } + + /** + * @magentoAppArea adminhtml + */ + public function testInheritanceBasedAdminhtmlActionDispatchesEvents() + { + $this->fakeAuthenticatedBackendRequest(); + + $this->setupEventManagerSpy(); + + /** @var InheritanceBasedBackendAction $action */ + $action = ObjectManager::getInstance()->create(InheritanceBasedBackendAction::class); + $this->configureRequestForAction('testroute', 'actionpath', 'actionname'); + + $action->dispatch($this->getRequest()); + + $this->assertPreAndPostDispatchEventsAreDispatched(); + } + + /** + * @magentoAppArea adminhtml + */ + public function testInterfaceOnlyAdminhtmlActionDispatchesEvents() + { + $this->setupEventManagerSpy(); + + /** @var InterfaceOnlyBackendAction $action */ + $action = ObjectManager::getInstance()->create(InterfaceOnlyBackendAction::class); + $this->configureRequestForAction('testroute', 'actionpath', 'actionname'); + + $action->execute(); + + $this->assertPreAndPostDispatchEventsAreDispatched(); + } + + /** + * @magentoAppArea frontend + */ + public function testSettingTheNoDispatchActionFlagProhibitsExecuteAndPostdispatchEvents() + { + $this->setupEventManagerSpy(); + + /** @var InterfaceOnlyFrontendAction $action */ + $action = ObjectManager::getInstance()->create(InterfaceOnlyFrontendAction::class); + $this->configureRequestForAction('testroute', 'actionpath', 'actionname'); + + /** @var ActionFlag $actionFlag */ + $actionFlag = ObjectManager::getInstance()->get(ActionFlag::class); + $actionFlag->set('', ActionInterface::FLAG_NO_DISPATCH, true); + + $action->execute(); + + $this->assertFalse($action->isExecuted(), 'The controller execute() method was not expected to be called.'); + $this->assertEventDispatchCount('controller_action_predispatch', 1); + $this->assertEventDispatchCount('controller_action_predispatch_testroute', 1); + $this->assertEventDispatchCount('controller_action_predispatch_testroute_actionpath_actionname', 1); + $this->assertEventDispatchCount('controller_action_postdispatch_testroute_actionpath_actionname', 0); + $this->assertEventDispatchCount('controller_action_postdispatch_testroute', 0); + $this->assertEventDispatchCount('controller_action_postdispatch', 0); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InheritanceBasedBackendAction.php b/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InheritanceBasedBackendAction.php new file mode 100644 index 0000000000000..b24cc2e30382c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InheritanceBasedBackendAction.php @@ -0,0 +1,46 @@ +pageFactory = $pageFactory; + } + + /** + * Creates Page + * + * @return ResponseInterface|ResultInterface|Page + */ + public function execute() + { + return $this->pageFactory->create(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InheritanceBasedFrontendAction.php b/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InheritanceBasedFrontendAction.php new file mode 100644 index 0000000000000..315df9585c715 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InheritanceBasedFrontendAction.php @@ -0,0 +1,63 @@ +pageFactory = $pageFactory; + } + + /** + * Runs `execute()` method to create Page + * + * @return ResponseInterface|ResultInterface|Page + */ + public function execute() + { + $this->executeWasCalled = true; + return $this->pageFactory->create(); + } + + /** + * Determines whether execute method was called + * + * @return bool + */ + public function isExecuted(): bool + { + return $this->executeWasCalled; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InterfaceOnlyBackendAction.php b/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InterfaceOnlyBackendAction.php new file mode 100644 index 0000000000000..86244fd67237b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InterfaceOnlyBackendAction.php @@ -0,0 +1,43 @@ +pageFactory = $pageFactory; + } + + /** + * Creates Page object + * + * @return ResponseInterface|ResultInterface|Page + */ + public function execute() + { + return $this->pageFactory->create(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InterfaceOnlyFrontendAction.php b/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InterfaceOnlyFrontendAction.php new file mode 100644 index 0000000000000..123fe2ea87be1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/TestStubs/InterfaceOnlyFrontendAction.php @@ -0,0 +1,59 @@ +pageFactory = $pageFactory; + } + + /** + * Creates Page object + * + * @return ResponseInterface|ResultInterface|Page + */ + public function execute() + { + $this->executeWasCalled = true; + return $this->pageFactory->create(); + } + + /** + * Returns whether `execute()` method was ran + * + * @return bool + */ + public function isExecuted(): bool + { + return $this->executeWasCalled; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/Billing/AgreementTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Billing/AgreementTest.php index fd8b4fd2efad5..6f192b6479acd 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Controller/Billing/AgreementTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Billing/AgreementTest.php @@ -19,6 +19,7 @@ class AgreementTest extends \Magento\TestFramework\TestCase\AbstractController * * @magentoDataFixture Magento/Customer/_files/customer.php * @magentoDbIsolation enabled + * @magentoAppArea frontend */ public function testReturnWizardAction() { diff --git a/lib/internal/Magento/Framework/App/Action/Action.php b/lib/internal/Magento/Framework/App/Action/Action.php index b68e7e873be6a..6a3b665c7d3ed 100644 --- a/lib/internal/Magento/Framework/App/Action/Action.php +++ b/lib/internal/Magento/Framework/App/Action/Action.php @@ -3,20 +3,29 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Action; +use Magento\Framework\App\ActionFlag; use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\Response\RedirectInterface; use Magento\Framework\App\ResponseInterface; -use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\App\ViewInterface; +use Magento\Framework\Event\ManagerInterface as EventManagerInterface; use Magento\Framework\Exception\NotFoundException; +use Magento\Framework\Message\ManagerInterface as MessageManagerInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Profiler; +use Magento\Framework\UrlInterface; /** * Extend from this class to create actions controllers in frontend area of your application. * It contains standard action behavior (event dispatching, flag checks) * Action classes that do not extend from this class will lose this behavior and might not function correctly * - * TODO: Remove this class. Allow implementation of Action Controllers by just implementing Action Interface. + * @deprecated Use \Magento\Framework\App\ActionInterface * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.NumberOfChildren) @@ -24,7 +33,7 @@ abstract class Action extends AbstractAction { /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ protected $_objectManager; @@ -37,32 +46,32 @@ abstract class Action extends AbstractAction protected $_sessionNamespace; /** - * @var \Magento\Framework\Event\ManagerInterface + * @var EventManagerInterface */ protected $_eventManager; /** - * @var \Magento\Framework\App\ActionFlag + * @var ActionFlag */ protected $_actionFlag; /** - * @var \Magento\Framework\App\Response\RedirectInterface + * @var RedirectInterface */ protected $_redirect; /** - * @var \Magento\Framework\App\ViewInterface + * @var ViewInterface */ protected $_view; /** - * @var \Magento\Framework\UrlInterface + * @var UrlInterface */ protected $_url; /** - * @var \Magento\Framework\Message\ManagerInterface + * @var MessageManagerInterface */ protected $messageManager; @@ -92,35 +101,15 @@ public function dispatch(RequestInterface $request) { $this->_request = $request; $profilerKey = 'CONTROLLER_ACTION:' . $request->getFullActionName(); - $eventParameters = ['controller_action' => $this, 'request' => $request]; - $this->_eventManager->dispatch('controller_action_predispatch', $eventParameters); - $this->_eventManager->dispatch('controller_action_predispatch_' . $request->getRouteName(), $eventParameters); - $this->_eventManager->dispatch( - 'controller_action_predispatch_' . $request->getFullActionName(), - $eventParameters - ); - \Magento\Framework\Profiler::start($profilerKey); + Profiler::start($profilerKey); $result = null; if ($request->isDispatched() && !$this->_actionFlag->get('', self::FLAG_NO_DISPATCH)) { - \Magento\Framework\Profiler::start('action_body'); + Profiler::start('action_body'); $result = $this->execute(); - \Magento\Framework\Profiler::start('postdispatch'); - if (!$this->_actionFlag->get('', self::FLAG_NO_POST_DISPATCH)) { - $this->_eventManager->dispatch( - 'controller_action_postdispatch_' . $request->getFullActionName(), - $eventParameters - ); - $this->_eventManager->dispatch( - 'controller_action_postdispatch_' . $request->getRouteName(), - $eventParameters - ); - $this->_eventManager->dispatch('controller_action_postdispatch', $eventParameters); - } - \Magento\Framework\Profiler::stop('postdispatch'); - \Magento\Framework\Profiler::stop('action_body'); + Profiler::stop('action_body'); } - \Magento\Framework\Profiler::stop($profilerKey); + Profiler::stop($profilerKey); return $result ?: $this->_response; } @@ -159,9 +148,9 @@ protected function _forward($action, $controller = null, $module = null, array $ /** * Set redirect into response * - * @param string $path - * @param array $arguments - * @return ResponseInterface + * @param string $path + * @param array $arguments + * @return ResponseInterface */ protected function _redirect($path, $arguments = []) { @@ -170,6 +159,8 @@ protected function _redirect($path, $arguments = []) } /** + * Returns ActionFlag value + * * @return \Magento\Framework\App\ActionFlag */ public function getActionFlag() diff --git a/lib/internal/Magento/Framework/App/Action/Plugin/ActionFlagNoDispatchPlugin.php b/lib/internal/Magento/Framework/App/Action/Plugin/ActionFlagNoDispatchPlugin.php new file mode 100644 index 0000000000000..263e3663513d3 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Action/Plugin/ActionFlagNoDispatchPlugin.php @@ -0,0 +1,53 @@ +actionFlag = $actionFlag; + $this->response = $response; + } + + /** + * Do not call proceed if the no dispatch action flag is set. + * + * @param ActionInterface $subject + * @param callable $proceed + * @return ResponseInterface + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundExecute(ActionInterface $subject, callable $proceed) + { + return $this->actionFlag->get('', ActionInterface::FLAG_NO_DISPATCH) ? $this->response : $proceed(); + } +} diff --git a/lib/internal/Magento/Framework/App/Action/Plugin/EventDispatchPlugin.php b/lib/internal/Magento/Framework/App/Action/Plugin/EventDispatchPlugin.php new file mode 100644 index 0000000000000..7d07d1f4cf457 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Action/Plugin/EventDispatchPlugin.php @@ -0,0 +1,138 @@ +request = $request; + $this->eventManager = $eventManager; + $this->actionFlag = $actionFlag; + } + + /** + * Trigger the controller_action_predispatch events + * + * @param ActionInterface $subject + */ + public function beforeExecute(ActionInterface $subject) + { + $this->dispatchPreDispatchEvents($subject); + } + + /** + * Build the event parameter array + * + * @param ActionInterface $subject + * @return array + */ + private function getEventParameters(ActionInterface $subject): array + { + return ['controller_action' => $subject, 'request' => $this->request]; + } + + /** + * Trigger the controller_action_postdispatch events if the suppressing action flag is not set + * + * @param ActionInterface $subject + * @param ResultInterface|Response|null $result + * @return ResultInterface|Response|null + */ + public function afterExecute(ActionInterface $subject, $result) + { + if (!$this->isSetActionNoPostDispatchFlag()) { + $this->dispatchPostDispatchEvents($subject); + } + + return $result; + } + + /** + * Check if action flags are set that would suppress the post dispatch events. + * + * @return bool + */ + private function isSetActionNoPostDispatchFlag(): bool + { + return $this->actionFlag->get('', Action::FLAG_NO_DISPATCH) || + $this->actionFlag->get('', Action::FLAG_NO_POST_DISPATCH); + } + + /** + * Dispatch the controller_action_predispatch events. + * + * @param ActionInterface $action + */ + private function dispatchPreDispatchEvents(ActionInterface $action) + { + $this->eventManager->dispatch('controller_action_predispatch', $this->getEventParameters($action)); + $this->eventManager->dispatch( + 'controller_action_predispatch_' . $this->request->getRouteName(), + $this->getEventParameters($action) + ); + $this->eventManager->dispatch( + 'controller_action_predispatch_' . $this->request->getFullActionName(), + $this->getEventParameters($action) + ); + } + + /** + * Dispatch the controller_action_postdispatch events. + * + * @param ActionInterface $action + */ + private function dispatchPostDispatchEvents(ActionInterface $action) + { + Profiler::start('postdispatch'); + $this->eventManager->dispatch( + 'controller_action_postdispatch_' . $this->request->getFullActionName(), + $this->getEventParameters($action) + ); + $this->eventManager->dispatch( + 'controller_action_postdispatch_' . $this->request->getRouteName(), + $this->getEventParameters($action) + ); + $this->eventManager->dispatch('controller_action_postdispatch', $this->getEventParameters($action)); + Profiler::stop('postdispatch'); + } +} diff --git a/lib/internal/Magento/Framework/App/Action/Plugin/Design.php b/lib/internal/Magento/Framework/App/Action/Plugin/LoadDesignPlugin.php similarity index 53% rename from lib/internal/Magento/Framework/App/Action/Plugin/Design.php rename to lib/internal/Magento/Framework/App/Action/Plugin/LoadDesignPlugin.php index 2893f1209dc98..2cda49c43c2ce 100644 --- a/lib/internal/Magento/Framework/App/Action/Plugin/Design.php +++ b/lib/internal/Magento/Framework/App/Action/Plugin/LoadDesignPlugin.php @@ -3,29 +3,38 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\App\Action\Plugin; +use Magento\Framework\App\ActionInterface; +use Magento\Framework\Config\Dom\ValidationException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Message\ManagerInterface as MessageManagerInterface; use Magento\Framework\Message\MessageInterface; +use Magento\Framework\View\DesignLoader; -class Design +/** + * Handling Exceptions on Design Loading + */ +class LoadDesignPlugin { /** - * @var \Magento\Framework\View\DesignLoader + * @var DesignLoader */ protected $_designLoader; /** - * @var \Magento\Framework\Message\ManagerInterface + * @var MessageManagerInterface */ protected $messageManager; /** - * @param \Magento\Framework\View\DesignLoader $designLoader - * @param \Magento\Framework\Message\ManagerInterface $messageManager + * @param DesignLoader $designLoader + * @param MessageManagerInterface $messageManager */ public function __construct( - \Magento\Framework\View\DesignLoader $designLoader, - \Magento\Framework\Message\ManagerInterface $messageManager + DesignLoader $designLoader, + MessageManagerInterface $messageManager ) { $this->_designLoader = $designLoader; $this->messageManager = $messageManager; @@ -34,20 +43,16 @@ public function __construct( /** * Initialize design * - * @param \Magento\Framework\App\ActionInterface $subject - * @param \Magento\Framework\App\RequestInterface $request - * + * @param ActionInterface $subject * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function beforeDispatch( - \Magento\Framework\App\ActionInterface $subject, - \Magento\Framework\App\RequestInterface $request - ) { + public function beforeExecute(ActionInterface $subject) + { try { $this->_designLoader->load(); - } catch (\Magento\Framework\Exception\LocalizedException $e) { - if ($e->getPrevious() instanceof \Magento\Framework\Config\Dom\ValidationException) { + } catch (LocalizedException $e) { + if ($e->getPrevious() instanceof ValidationException) { /** @var MessageInterface $message */ $message = $this->messageManager ->createMessage(MessageInterface::TYPE_ERROR) diff --git a/lib/internal/Magento/Framework/App/ActionInterface.php b/lib/internal/Magento/Framework/App/ActionInterface.php index 921e1a2e16b1e..1501abe9eb956 100644 --- a/lib/internal/Magento/Framework/App/ActionInterface.php +++ b/lib/internal/Magento/Framework/App/ActionInterface.php @@ -25,8 +25,6 @@ interface ActionInterface /** * Execute action based on request and return result * - * Note: Request will be added as operation argument in future - * * @return \Magento\Framework\Controller\ResultInterface|ResponseInterface * @throws \Magento\Framework\Exception\NotFoundException */ diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Action/ActionTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Action/ActionTest.php index ebd72f5badccf..c2d30187845a4 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Action/ActionTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Action/ActionTest.php @@ -8,95 +8,87 @@ use \Magento\Framework\App\Action\Action; +use Magento\Framework\App\ActionFlag; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\App\Response\RedirectInterface; +use Magento\Framework\App\ResponseInterface; +use Magento\Framework\App\ViewInterface; +use Magento\Framework\Event\ManagerInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\View\Page\Config as PageConfig; +use PHPUnit\Framework\MockObject\MockObject; class ActionTest extends \PHPUnit\Framework\TestCase { - /** @var \Magento\Framework\App\Test\Unit\Action\ActionFake */ + /** + * @var ActionFake + */ protected $action; - /** @var ObjectManagerHelper */ + /** + * @var ObjectManagerHelper + */ protected $objectManagerHelper; /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + * @var HttpRequest|MockObject */ protected $_requestMock; /** - * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ResponseInterface|MockObject */ protected $_responseMock; /** - * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ManagerInterface|MockObject */ protected $_eventManagerMock; /** - * @var \Magento\Framework\App\ActionFlag|\PHPUnit_Framework_MockObject_MockObject + * @var ActionFlag|MockObject */ protected $_actionFlagMock; /** - * @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit_Framework_MockObject_MockObject + * @var RedirectInterface|MockObject */ protected $_redirectMock; /** - * @var \Magento\Framework\App\ViewInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ViewInterface|MockObject */ protected $viewMock; /** - * @var \Magento\Framework\View\Page\Config|\PHPUnit_Framework_MockObject_MockObject + * @var PageConfig|MockObject */ protected $pageConfigMock; - /** - * Full action name - */ - const FULL_ACTION_NAME = 'module/controller/someaction'; - - /** - * Route name - */ - const ROUTE_NAME = 'module/controller/actionroute'; - - /** - * Action name - */ - const ACTION_NAME = 'someaction'; - - /** - * Controller name - */ - const CONTROLLER_NAME = 'controller'; - - /** - * Module name - */ - const MODULE_NAME = 'module'; + public const FULL_ACTION_NAME = 'module/controller/someaction'; + public const ROUTE_NAME = 'module/controller/actionroute'; + public const ACTION_NAME = 'someaction'; + public const CONTROLLER_NAME = 'controller'; + public const MODULE_NAME = 'module'; public static $actionParams = ['param' => 'value']; protected function setUp() { - $this->_eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); - $this->_actionFlagMock = $this->createMock(\Magento\Framework\App\ActionFlag::class); - $this->_redirectMock = $this->createMock(\Magento\Framework\App\Response\RedirectInterface::class); - $this->_requestMock = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class) - ->disableOriginalConstructor()->getMock(); - $this->_responseMock = $this->createMock(\Magento\Framework\App\ResponseInterface::class); - - $this->pageConfigMock = $this->createPartialMock(\Magento\Framework\View\Page\Config::class, ['getConfig']); - $this->viewMock = $this->createMock(\Magento\Framework\App\ViewInterface::class); + $this->_eventManagerMock = $this->createMock(ManagerInterface::class); + $this->_actionFlagMock = $this->createMock(ActionFlag::class); + $this->_redirectMock = $this->createMock(RedirectInterface::class); + $this->_requestMock = $this->createMock(HttpRequest::class); + $this->_responseMock = $this->createMock(ResponseInterface::class); + + $this->pageConfigMock = $this->createPartialMock(PageConfig::class, ['getConfig']); + $this->viewMock = $this->createMock(ViewInterface::class); $this->viewMock->expects($this->any())->method('getPage')->will($this->returnValue($this->pageConfigMock)); - $this->pageConfigMock->expects($this->any())->method('getConfig')->will($this->returnValue(1)); + $this->pageConfigMock->expects($this->any())->method('getConfig')->willReturn(1); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->action = $this->objectManagerHelper->getObject( - \Magento\Framework\App\Test\Unit\Action\ActionFake::class, + ActionFake::class, [ 'request' => $this->_requestMock, 'response' => $this->_responseMock, @@ -111,29 +103,12 @@ protected function setUp() public function testDispatchPostDispatch() { - $this->_requestMock->expects($this->exactly(3))->method('getFullActionName')->will( - $this->returnValue(self::FULL_ACTION_NAME) - ); - $this->_requestMock->expects($this->exactly(2))->method('getRouteName')->will( - $this->returnValue(self::ROUTE_NAME) - ); - $expectedEventParameters = ['controller_action' => $this->action, 'request' => $this->_requestMock]; - $this->_eventManagerMock->expects($this->at(0))->method('dispatch')->with( - 'controller_action_predispatch', - $expectedEventParameters - ); - $this->_eventManagerMock->expects($this->at(1))->method('dispatch')->with( - 'controller_action_predispatch_' . self::ROUTE_NAME, - $expectedEventParameters - ); - $this->_eventManagerMock->expects($this->at(2))->method('dispatch')->with( - 'controller_action_predispatch_' . self::FULL_ACTION_NAME, - $expectedEventParameters - ); - - $this->_requestMock->expects($this->once())->method('isDispatched')->will($this->returnValue(true)); - $this->_actionFlagMock->expects($this->at(0))->method('get')->with('', Action::FLAG_NO_DISPATCH)->will( - $this->returnValue(false) + $this->_requestMock->method('getFullActionName')->willReturn(self::FULL_ACTION_NAME); + $this->_requestMock->method('getRouteName')->willReturn(self::ROUTE_NAME); + $this->_requestMock->method('isDispatched')->willReturn(true); + $this->_actionFlagMock->method('get')->willReturnMap( + ['', Action::FLAG_NO_DISPATCH, false], + ['', Action::FLAG_NO_POST_DISPATCH] ); // _forward expectations @@ -151,23 +126,6 @@ public function testDispatchPostDispatch() self::$actionParams ); - $this->_actionFlagMock->expects($this->at(1))->method('get')->with('', Action::FLAG_NO_POST_DISPATCH)->will( - $this->returnValue(false) - ); - - $this->_eventManagerMock->expects($this->at(3))->method('dispatch')->with( - 'controller_action_postdispatch_' . self::FULL_ACTION_NAME, - $expectedEventParameters - ); - $this->_eventManagerMock->expects($this->at(4))->method('dispatch')->with( - 'controller_action_postdispatch_' . self::ROUTE_NAME, - $expectedEventParameters - ); - $this->_eventManagerMock->expects($this->at(5))->method('dispatch')->with( - 'controller_action_postdispatch', - $expectedEventParameters - ); - $this->assertEquals($this->_responseMock, $this->action->dispatch($this->_requestMock)); } } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Action/Plugin/DesignTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Action/Plugin/DesignTest.php deleted file mode 100644 index d5c7f4d0355ca..0000000000000 --- a/lib/internal/Magento/Framework/App/Test/Unit/Action/Plugin/DesignTest.php +++ /dev/null @@ -1,20 +0,0 @@ -createMock(\Magento\Framework\App\Action\Action::class); - $designLoaderMock = $this->createMock(\Magento\Framework\View\DesignLoader::class); - $messageManagerMock = $this->createMock(\Magento\Framework\Message\ManagerInterface::class); - $requestMock = $this->createMock(\Magento\Framework\App\RequestInterface::class); - $plugin = new \Magento\Framework\App\Action\Plugin\Design($designLoaderMock, $messageManagerMock); - $designLoaderMock->expects($this->once())->method('load'); - $plugin->beforeDispatch($subjectMock, $requestMock); - } -} diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Action/Plugin/LoadDesignPluginTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Action/Plugin/LoadDesignPluginTest.php new file mode 100644 index 0000000000000..90acfde426931 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Test/Unit/Action/Plugin/LoadDesignPluginTest.php @@ -0,0 +1,34 @@ +createMock(Action::class); + + /** @var MockObject|DesignLoader $designLoaderMock */ + $designLoaderMock = $this->createMock(DesignLoader::class); + + /** @var MockObject|ManagerInterface $messageManagerMock */ + $messageManagerMock = $this->createMock(ManagerInterface::class); + + $plugin = new LoadDesignPlugin($designLoaderMock, $messageManagerMock); + + $designLoaderMock->expects($this->once())->method('load'); + $plugin->beforeExecute($actionMock); + } +}